新人第一次在 CNode 社区发文,欢迎讨论和指正!原文发布在 SegmentFault ,有兴趣的可以去瞄一下。
概述
我最近在整理一个 Ionic + Webpack 的项目模板,因为项目代码都是 ES6 的,所以我也想在其他地方也用 ES6 。其中一个地方就是 webpack.config.js
。目前有三种方法可以做到这一点,不过各有利弊。
方法 1 :升级到 Node.js 4
Node.js 4 合并了 io.js ,所以自然带有所有 io.js 的特性,其中就包括部分 ES6 特性的支持。不过目前的版本 (4.2.1) 只支持部分特性,尤其是以下几个很常用的都不支持:
- 函数默认值
- 解构和其相关的所有功能
- ES6 模块
具体支持程度可看 这里 。Babel 达到了 71% ,Node.js 4 达到了 53% ,Node.js 5 也只达到了 59% 。真是不容乐观。
总结:这个方法适合依赖少数 ES6 特性,又确定使用 Node.js 4 及以上版本的人,不能算是大众方案。
方法 2 :webpack.config.babel.js
这个最简单,把 webpack.config.js
改名成 webpack.config.babel.js
就行。一切命令照旧。Webpack 在执行时会先用 Babel 把配置文件转成 ES5 代码再继续处理。一切 Babel 支持的语言特性都可以用。
这是一个 Webpack 支持,但文档里完全没有提到的特性 (应该马上就会加上)。只要你把配置文件命名成 webpack.config.[loader].js
,Webpack 就会用相应的 loader 去转换一遍配置文件。所以要使用这个方法,你需要安装 babel-loader 和 babel-core 两个包。记住你不需要完整的 babel 包。
理论上这种做法支持任何 loader ,所以你也可以用 CoffeeScript 或者其他语言去写,只要有相应的 loader 就行。
这个方法还有个好处,如果你在 webpack.config.babel.js
里 import
了其他文件,那个文件也会被 Babel 编译。比如:
// webpack.config.babel.js
// 这个文件也可以用 ES6 写
import config from './some-config'
export default {
// webpack config
}
不过,如果你打算自己写脚本去加载 Webpack 的配置,这个方法就不管用了。
总结:这个方法适合那些不在乎 Node.js 版本,只使用 webpack
和 webpack-dev-server
命令,不打算自己写脚本或过多折腾,但想使用完整的 ES6 特性的人。
方法 3 :用 babel-node
这是我在 这个问题 中看到的。其中提问者提到的 React Starter Kit 挺有意思。它没改 webpack.config.js
的文件名,但配置文件和各种脚本都是完全的 ES6 语法。这是怎么做到的呢?
关键就在于 babel-node
命令。这是 Babel 提供的一个命令行工具,你可以用它代替 node
去执行文件。文件会被 Babel 编译后再交给 node
命令执行。
让我们看看 React Starter Kit 如何利用这一点的。首先它用 package.json
里定义的 scripts
来代替 webpack
命令。可以看到它完全使用了 babel-node
命令代替 node
。比如:
{
"scripts": {
"bundle": "babel-node tools/run bundle",
...
}
}
这样就可以用 npm run bundle
来执行相应的任务了。这个命令会会先调用 tools/run.js
,然后调用 tools/bundle.js
,然后加载 tools/webpack.config.js
。整个流程中的所有文件都是用 ES6 和 ES7 语法写的,挺整洁漂亮。
总结:这个方法适合需要自己写脚本并且想用完整的 ES6 语法的人。不过 babel-node
因为要编译,而且换成结果会存在内存中,所以命令执行时间会比单纯使用 node
要长(主要是启动时间)。这点就见仁见智了。记住不要在生产环境下用 babel-node
。
总结
得益于 Babel ,ES6 几乎已经是现在的标配了。在不折腾的情况下用用 ES6 是大家都能接受的结果。所以我推荐大部分人用方法 2 。但如果需要写点 npm run xxx
的脚本,难免又会觉得不能用 ES6 有点不一致。这种情况我觉得要么就都用 ES6 ,要么就干脆不用。因为我个人觉得一致性比用不用 ES6 更加重要。build 脚本勉强也算是后端的一部分,而我们不能强求所有后端代码都写成 ES6 的(比如自己写个 server)。
参考资料
Allow webpack.config.js to be written in ES6 ES6 Compatible Table StackOverflow - How to use ES6 in Webpack config React Starter Kit Babel CLI
方法 2 就是啊,已经支持了,只是文档没有写。
mark
方法 2 报这个错
@xwartz 不需要指定 --config
方法2是很棒的可行方案
@darkbaby123 ,我在package.json中添加了babel-core,babel-loader,babel-register 都是save-dev的,而且也在global中添加了这三个module,按照你的说明,将webpack.config.js更改为了webpack.config.babel.js,然而运行webpack命令的时候并没有支持es6的语法
import conf from './config/base';
module.exports = {
entry:__dirname + "/app/main.js",
output:{
path:__dirname + "/public",
filename:"bundle.js"
}
}
依然会报下面的饿错误
(function (exports, require, module, __filename, __dirname) { import conf from './config/base';
^^^^^^
SyntaxError: Unexpected token import
at createScript (vm.js:53:10)
at Object.runInThisContext (vm.js:95:10)
at Module._compile (module.js:543:28)
亲自测试,发现如果让webpack.config.js文件本身支持es6的写法,需要如下几个步骤: 1、需要安装了babel-core (npm i babel-core --save-dev) 2、需要安装了babel-preset-es2015 (npm i babel-preset-es2015 --save-dev) 3、需要在项目的根目录设置.babelrc文件,并在其中指定presets:[‘es2015’] 4、需要将webpack.config.js 重命名为webpack.config.babel.js
// in webpack.config.babel.js
import devtool_conf from './config/devtool';
import devserver_conf from './config/devserver';
export default {
entry:__dirname + "/app/main.js",
output:{
path:__dirname + "/public",
filename:"bundle.js"
},
devtool:devtool_conf,
devServer:devserver_conf
}
// in config/devserver.js
const path = require('path');
const root = path.join(__dirname,"../");
export default {
contentBase: root + "/public",
inline: true
}