babel-loader,webpack,ES2015模块:"元素类型无效"

时间:2015-12-17 23:59:09

标签: reactjs ecmascript-6 webpack babeljs

Github回购所有内容:https://github.com/b-paul/react-lifecycle

更新12/18:问题的很大一部分是用于运行项目的npm命令。我注意到npm build没有成功,但npm start报告建立正常。完整的答案如下,为什么没有按预期工作。这个问题的其余部分是为后人保留的。

我的第一个webpack项目的基本设置有问题。我使用的是React和Babel,以及以下webpack.config.js

var path = require('path');

module.exports = {
  entry: [ path.resolve('./js/app.js'),
           'webpack-dev-server/client?http://localhost:8080' ],
  output: {
    path: path.resolve('./js/build'),
    filename: 'app.min.js'
  },
  module: {
    loaders: [
      { test: /\.jsx?$/,
        loader: 'babel',
        query: {
          presets: ['react', 'stage-1', 'es2015']
        },
        include: path.resolve('js/') } ]
  },
  devtool: 'source-map'
};

js/app.js

import Lifecycle from './components/lifecycle';
import React from 'react';
import {render} from 'react-dom';

var shell = document.createElement('div');
shell.className = 'app-shell';
document.body.appendChild(shell);
render(<Lifecycle />, shell);

js/components/lifecycle.js

import React from 'react';

class Lifecycle extends React.Component {
  render() {
    return (
      <div>Hello, world</div>
    );
  }
}

export default Lifecycle;

以上构建没有错误,但它不会渲染&#34; Hello,world&#34;。我收到错误,&#34;不变违规:元素类型无效:期望一个字符串(对于内置组件)或类/函数(对于复合组件)但得到:undefined。&#34;在浏览器控制台中。

我可以跟踪一些生成的babel代码,试图检查我的模块Lifecycle是否是ES6模块(babel认为是这样)并期望它有一个属性default on内部模块对象(它没有)。这是生成的代码:

/* 0 */
/***/ function(module, exports, __webpack_require__) {

  'use strict';

  var _lifecycle = __webpack_require__(1);

  var _lifecycle2 = _interopRequireDefault(_lifecycle);

  var _react = __webpack_require__(2);

  var _react2 = _interopRequireDefault(_react);

  var _reactDom = __webpack_require__(159);

  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

  (0, _reactDom.render)(_react2.default.createElement(_lifecycle2.default, null), document.body);

/***/ }

最后注意事项:我多次引用https://github.com/code0wl/react-example-es2015进行设置,我可以将该示例repo克隆并构建到一个正常工作的应用程序中,没有任何问题。我意识到我必须错过该回购中发生的一些重要部分,但我无法看到它。

4 个答案:

答案 0 :(得分:1)

适合我

git clone https://github.com/b-paul/react-lifecycle.git
cd react-lifecycle.git
npm install
npm run build
npm run start
# go to http://localhost:8090/index.html    

答案 1 :(得分:0)

是否有理由在app.js中动态创建应用的容器div,而不是仅仅将其放入index.html?我克隆了您的repo并通过进行以下更改来构建应用程序:

<强>的index.html:

<body>
   <div id="app-shell"></div>
   <script type="application/javascript" src="js/build/app.min.js"></script>
</body>

<强> app.js

import React from 'react';
import {render} from 'react-dom';
import Lifecycle from './components/lifecycle';

render(<Lifecycle />, document.getElementById('app-shell'));

我认为“Element type is invalid”错误是一个红色的鲱鱼。在此之前,我看到了:

  

警告:React.createElement:type不应为null,未定义,   布尔值或数字。它应该是一个字符串(对于DOM元素)或a   ReactClass(用于复合组件).warning @   app.min.js:2233createElement @ app.min.js:19531(匿名函数)@   app.min.js:61__webpack_require__ @ app.min.js:20(匿名函数)@   app.min.js:40(匿名函数)@ app.min.js:43 app.min.js:2233   警告:render():将组件直接渲染到document.body中   气馁,因为它的孩子经常被第三方操纵   脚本和浏览器扩展。这可能会导致微妙的和解   的问题。尝试渲染为为您的应用创建的容器元素。

这可能是由于您在app.js ...

中创建shell元素的方式

答案 2 :(得分:0)

这个问题应该被称为&#34;为什么我的NPM脚本不会更新我的捆绑包。&#34;

在开发早期的某个时刻,我已成功将我的代码与webpack捆绑在一起。该捆绑包在磁盘上为js/build/app.min.js。在那之后,我以为我正在使用来自package.json的NPM脚本来重建每次更改的应用程序,但是在浏览器中,我仍然得到旧的行为(来自原始包)。我错过了两个事实:

事实1: npm build是一个公认的NPM命令,但 scripts.build调用package.json。和@ zhongjie-wu&#39; answer一样,我需要做npm run build。另一方面,npm start 调用scripts.start,它成功构建了一个包含webpack-dev-server的包。

事实2: webpack-dev-server在提供重建捆绑包时,无法将webpack配置文件中的output.path识别为路由的一部分。因此,根据我使用的配置,webpack构建为/js/build/app.min.js,但webpack-dev-server将来自内存的捆绑服务/app.min.js。由于我的HTML引用了原始文件,因此我没有看到开发服务器软件包。

答案 3 :(得分:0)

<强> Layout.js

export default class Layout extends Component {
  constructor(props) {
   super(props);
  }

  render() {
    return (
      <div className="Layout">

      </div>
    )
  }
};

<强> .babelrc 需要为try transpiling classes添加stage-1预设

    {
      "presets": ["stage-1", "es2015", "react"],
      "plugins": ["transform-runtime"]
    }

并且输入文件需要执行ES5导出:

import React from 'react';
import Layout from './Layout';
import {render} from 'react-dom';

if (typeof document !== 'undefined') {
  render(<Layout />, document.getElementById('app'));
}

module.exports = Layout;

为我工作