webpack 从 v1 迁移到 v2

resolve.root, resolve.fallback, resolve.modulesDirectories

上述配置项被一个单独的配置项 resolve.modules 取代。详见 resolving。css

resolve: {
-   root: path.join(__dirname, "src")
+   modules: [
+     path.join(__dirname, "src"),
+     "node_modules"
+   ]
  }
resolve.extensions

此配置项再也不须要传一个空字符串。此行为被迁移到 resolve.enforceExtension。详见 resolving。node

resolve.*webpack

还有更多的变化,因为不经常使用,不在这里详细列出。详见 resolving。web

module.loaders 改为了 module.rules

旧的 loader 配置被更强大的 rules 系统取代,后者容许配置 loader 以及其余更多项。为了兼容旧版,module.loaders 语法被保留,旧的属性名依然能够被解析。新的命名约定更易于理解而且是升级配置使用 module.rules 的好理由。npm

module: {
-   loaders: [
+   rules: [
      {
        test: /\.css$/,
-       loaders: [
+       use: [
          {
            loader: "style-loader"
          },
          {
            loader: "css-loader",
-           query: {
+           options: {
              modules: true
            }
          }
        ]
      },
      {
        test: /\.jsx$/,
        loader: "babel-loader", // Do not use "use" here
        options: {
          // ...
        }
      }
    ]
  }

链式 loaders

与 v1 版本相同,loaders 能够链式调用,上一个 loader 的输出被做为输入传给下一个 loader。使用 rule.use 配置项,use 能够设置为一个 loaders 的列表。在 v1 版本中,loaders 一般被用 ! 连写。这一写法在新版中只在使用旧的 module.loaders 时有效。json

module: {
-   loaders: {
+   rules: [{
      test: /\.less$/,
-     loader: "style-loader!css-loader!less-loader"
+     use: [
+       "style-loader",
+       "css-loader",
+       "less-loader"
+     ]
    }]
  }

取消了在模块名中自动添加 -loader 后缀

It is not possible anymore to omit the -loader extension when referencing loaders:babel

module: {
    rules: [
      {
        use: [
-         "style",
+         "style-loader",
-         "css",
+         "css-loader",
-         "less",
+         "less-loader",
        ]
      }
    ]
  }

你仍然能够启用这一旧行为,方法是经过配置 resolveLoader.moduleExtensions 项,可是咱们不推荐这么作。less

+ resolveLoader: {
+   moduleExtensions: ["-loader"]
+ }

json-loader 再也不须要手动添加

若是没有为 JSON 文件配置 loader,webpack 将自动尝试经过 加载 json-loader JSON 文件。dom

module: {
    rules: [
-     {
-       test: /\.json/,
-       loader: "json-loader"
-     }
    ]
  }

咱们决定这么作 以消弭 webpack、 node.js 和 browserify 之间的环境差别。异步

loader 默认的 resolve 配置是相对于 context 的

在 webpack 1 中,loader 默认配置下 resolve 相对于被匹配的文件。而在 webpack 2 中默认配置的 resolve 相对于 context 配置项。

这解决了一些问题,好比使用 npm link 或引用 context 以外的模块时致使重复载入。

你能够再也不须要使用一些变通方案了:

module: {
    rules: [
      {
        // ...
-       loader: require.resolve("my-loader")
+       loader: "my-loader"
      }
    ]
  },
  resolveLoader: {
-   root: path.resolve(__dirname, "node_modules")
  }

取消了 module.preLoaders 以及 module.postLoaders

module: {
-   preLoaders: [
+   rules: [
      {
        test: /\.js$/,
+       enforce: "pre",
        loader: "eslint-loader"
      }
    ]
  }

UglifyJsPlugin sourceMap

UglifyJsPlugin 的 sourceMap 配置项如今默认为 false 而不是 true。 这意味着若是你在压缩代码时启用了 source map,或者想要让 uglifyjs 的警告可以对应到正确的代码行,你须要将 UglifyJsPlugin 的 sourceMap 设为 true。

devtool: "source-map",
plugins: [
    new UglifyJsPlugin({
+     sourceMap: true
    })
]

UglifyJsPlugin warnings

UglifyJsPlugin 的 compress.warnings 配置项如今默认为 false 而不是 true。 这意味着若是你想要看到 uglifyjs 的警告信息,你须要将 compress.warnings 设为 true。

devtool: "source-map",
plugins: [

new UglifyJsPlugin({
  • compress: {

  • warnings: true

  • }

    })

    ]

UglifyJsPlugin 压缩 loaders

UglifyJsPlugin 再也不压缩 loaders。在将来很长一段时间里,须要经过设置 minimize:true 来压缩 loaders。参考 loader 文档里的相关配置项。

loaders 的压缩模式将在 webpack 3 或更高的版本中被取消。

为了兼容旧的 loaders,loaders 能够经过插件来切换到压缩模式:

plugins: [
+   new webpack.LoaderOptionsPlugin({
+     minimize: true
+   })
]

DedupePlugin 被移除

再也不须要 webpack.optimize.DedupePlugin。请从配置中移除。

BannerPlugin - 破坏性改动

BannerPlugin 不在接受两个参数而是只接受单独的 options 对象。

plugins: [
-    new webpack.BannerPlugin('Banner', {raw: true, entryOnly: true});
+    new webpack.BannerPlugin({banner: 'Banner', raw: true, entryOnly: true});
  ]

OccurrenceOrderPlugin 被默认加载

咱们再也不须要在配置里指定它:

plugins: [
-   new webpack.optimize.OccurrenceOrderPlugin()
  ]

ExtractTextWebpackPlugin - 大改变

ExtractTextPlugin 1.0.0 不能在 webpack v2 下工做。 你须要明确地安装 ExtractTextPlugin v2。

npm install --save-dev extract-text-webpack-plugin@beta

这一插件的配置变化主要体如今语法上。

ExtractTextPlugin.extract

module: {
  rules: [
    {
      test: /.css$/,
-      loader: ExtractTextPlugin.extract("style-loader", "css-loader", { publicPath: "/dist" })
+      use: ExtractTextPlugin.extract({
+        fallback: "style-loader",
+        use: "css-loader",
+        publicPath: "/dist"
+      })
    }
  ]
}

new ExtractTextPlugin({options})

plugins: [
-  new ExtractTextPlugin("bundle.css", { allChunks: true, disable: false })
+  new ExtractTextPlugin({
+    filename: "bundle.css",
+    disable: false,
+    allChunks: true
+  })
]

全动态 requires 如今默认会失败

只有一个表达式的依赖(例如 require(expr))将建立一个空的 context 而不是一个完整目录的 context。

若是有上面那样的代码,最好把它重构了,由于在 ES2015 模块下它不能够用。若是你肯定不会有 ES2015 模块,你可使用 ContextReplacementPlugin 来提示编译器进行正确的处理。

在 CLI 和配置中使用自定义参数

若是你以前滥用 CLI 来传自定义参数到配置中,好比:

webpack --custom-stuff

// webpack.config.js
var customStuff = process.argv.indexOf("--custom-stuff") >= 0;
/* ... */
module.exports = config;

你将会发现新版中再也不容许这么作。CLI 如今更加严格了。

替代地,如今提供了一个接口来传递参数给配置。咱们应该采用这种新方式,在将来许多工具将可能依赖它。

webpack --env.customStuff

module.exports = function(env) {
  var customStuff = env.customStuff;
  /* ... */
  return config;
};

详见 CLI。

require.ensure 以及 AMD require 的异步

如今这些函数老是异步的,而不是当 chunk 已经加载过的时候同步调用它们的 callback。

注意 require.ensure 如今依赖于原生的 Promise。若是在不支持 Promise 的环境里使用 require.ensure,你须要添加 polyfill。

经过 options 配置 loader

你不能再经过 webpack.config.js 的自定义属性来配置 loader。只能经过 options 来配置。下面配置的 ts 属性在 webpack 2 下再也不有效:

module.exports = {
  ...
  module: {
    rules: [{
      test: /\.tsx?$/,
      loader: 'ts-loader'
    }]
  },
  // does not work with webpack 2
  ts: { transpileOnly: false }
}

什么是 options?

好问题。严格来讲,有两种办法,均可以用来配置 webpack 的 loader。典型的 options 被称为 query,是一个能够被添加到 loader 名以后的字符串。它比较像一个 query string,可是实际上有更强大的能力:

module.exports = {
  ...
  module: {
    rules: [{
      test: /\.tsx?$/,
      loader: 'ts-loader?' + JSON.stringify({ transpileOnly: false })
    }]
  }
}

不过它也能够分开来,写成一个单独的对象,紧跟在 loader 属性后面:

module.exports = {
  ...
  module: {
    rules: [{
      test: /\.tsx?$/,
      loader: 'ts-loader',
      options:  { transpileOnly: false }
    }]
  }
}

LoaderOptionsPlugin context

有的 loader 须要从配置中读取一些 context 信息。在将来很长一段时间里,这将须要经过 loader options 传入。详见 loader 文档的相关选项。

为了保持对旧 loaders 的兼容,这些信息能够经过插件传进来:

plugins: [
+   new webpack.LoaderOptionsPlugin({
+     options: {
+       context: __dirname
+     }
+   })
  ]

debug

在 webpack 1 中 debug 配置项切换 loaders 到 debug 模式。在将来很长一段时间里,这将须要经过 loader 配置项传递。详见 loader 文档的相关选项。

loaders 的 debug 模式将在 webpack 3 或后续版本中取消。

为了保持对旧 loaders 的兼容,loader 能够经过插件来切换到 debug 模式:

- debug: true,
  plugins: [
+   new webpack.LoaderOptionsPlugin({
+     debug: true
+   })
  ]

ES2015 的代码分割

在 webpack v1 中,你能使用 require.ensure 做为方法来懒加载 chunks 到你的应用中:

require.ensure([], function(require) {
  var foo = require("./module");
});

ES2015 模块加载规范定义了 import() 方法来运行时动态地加载 ES2015 模块。

webpack 将 import() 做为分割点并将被请求的模块放到一个单独的 chunk 中。

import() 接收模块名做为参数,并返回一个 Promise。

function onClick() {
  import("./module").then(module => {
    return module.default;
  }).catch(err => {
    console.log("Chunk loading failed");
  });
}

好消息是:若是加载 chunk 失败,咱们能够进行处理,由于如今它基于 Promise。

警告:require.ensure 容许用可选的第三个参数为 chunk 简单命名,可是 import API 还未提供这个能力。若是你想要保留这个功能,你能够继续使用 require.ensure。

require.ensure([], function(require) {
var foo = require("./module");
}, "custom-chunk-name");
(注意废弃的 System.import:webpack 对 System.import 的使用不符合新提出的标准,因此它在 v2.1.0-beta.28 版本中被废弃,转向支持 import())

因为这个建议还在 Stage 3,若是你想要同时使用 import 和 Babel,你须要安装/添加 dynamic-import 语法插件来绕过解析错误。当建议被添加到规范以后,就再也不须要这个语法插件了。

动态表达式

能够传递部分表达式给 import()。这与 CommonJS 对表达式的处理方式一致(webpack 为全部可能匹配的文件建立 context)。

import() 为每个可能的模块建立独立的 chunk。

function route(path, query) {
  return import(`./routes/${path}/route`)
    .then(route => new route.Route(query));
}
// 上面代码为每一个可能的路由建立独立的 chunk

混合使用 ES201五、AMD 和 CommonJS

你能够自由混合使用三种模块类型(甚至在同一个文件中)。在这个状况中 webpack 的行为和 babel 以及 node-eps 一致:

// CommonJS consuming ES2015 Module
var book = require("./book");

book.currentPage;
book.readPage();
book.default === "This is a book";
// ES2015 Module consuming CommonJS
import fs from "fs"; // module.exports map to default
import { readFileSync } from "fs"; // named exports are read from returned object+

typeof fs.readFileSync === "function";
typeof readFileSync === "function";

It is important to note that you will want to tell Babel to not parse these module symbols so webpack can use them. You can do this by setting the following in your .babelrc or babel-loader options.

.babelrc

{
  "presets": [
    ["es2015", { "modules": false }]
  ]
}

Hints:不须要改变什么,不过也能够改变。

模板字符串

webpack 如今支持表达式中的模板字符串了。这意味着你能够在 webpack 构建中使用它们:

- require("./templates/" + name);
+ require(`./templates/${name}`);

配置中使用 Promise

webpack 如今支持在配置文件中返回 Promise 了。这让你能在配置文件中作异步处理。

webpack.config.js

module.exports = function() {
  return fetchLangs().then(lang => ({
    entry: "...",
    // ...
    plugins: [
      new DefinePlugin({ LANGUAGE: lang })
    ]
  }));
};

高级 loader 匹配

webpack 如今支持对 loader 进行更多方式的匹配。

module: {
  rules: [
    {
      resource: /filename/, // matches "/path/filename.js"
      resourceQuery: /querystring/, // matches "/filename.js?querystring"
      issuer: /filename/, // matches "/path/something.js" if requested from "/path/filename.js"
    }
  ]
}

复合 options

webpack 1 只支持可以 JSON.stringify 的对象做为配置项。webpack 2 如今支持任意 JS 对象做为 loader 配置项。

使用复合 options 只有一个附加条件。你须要在 options 对象上添加一个 ident,让它可以被其余 loader 引用。

options 对象上有了 ident ,内联的 loader 就能够引用这个 options 对象。下面是个例子:

require("some-loader??by-ident!resource")

{
  test: /.../,
  loader: "...",
  options: {
    ident: "by-ident",
    magic: () => return Math.random()
  }
}
相关文章
相关标签/搜索