用 ES6 编写 Webpack 的配置文件
发布于 9 年前 作者 darkbaby123 30171 次浏览 最后一次编辑是 8 年前 来自 分享

新人第一次在 CNode 社区发文,欢迎讨论和指正!原文发布在 SegmentFault ,有兴趣的可以去瞄一下。

概述

我最近在整理一个 Ionic + Webpack 的项目模板,因为项目代码都是 ES6 的,所以我也想在其他地方也用 ES6 。其中一个地方就是 webpack.config.js 。目前有三种方法可以做到这一点,不过各有利弊。

方法 1 :升级到 Node.js 4

Node.js 4 合并了 io.js ,所以自然带有所有 io.js 的特性,其中就包括部分 ES6 特性的支持。不过目前的版本 (4.2.1) 只支持部分特性,尤其是以下几个很常用的都不支持:

  1. 函数默认值
  2. 解构和其相关的所有功能
  3. 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-loaderbabel-core 两个包。记住你不需要完整的 babel 包。

理论上这种做法支持任何 loader ,所以你也可以用 CoffeeScript 或者其他语言去写,只要有相应的 loader 就行。

这个方法还有个好处,如果你在 webpack.config.babel.jsimport 了其他文件,那个文件也会被 Babel 编译。比如:

// webpack.config.babel.js

// 这个文件也可以用 ES6 写
import config from './some-config'

export default {
  // webpack config
}

不过,如果你打算自己写脚本去加载 Webpack 的配置,这个方法就不管用了。

总结:这个方法适合那些不在乎 Node.js 版本,只使用 webpackwebpack-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

8 回复

Webpack 都已经默认支持 Babel 启动了吗…

方法 2 就是啊,已经支持了,只是文档没有写。

untitled1.png

方法 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
}
回到顶部