Webpack2 晋级指南和特征择要

用时多日,webpack2.2正式版终究赶在年前宣布了,此次更新相对于1.X版本有了诸多的晋级优化革新,笔者也在第一时间查阅了官方的文档,整顿和翻译了由webpack1晋级到2所须要相识的API变动和注意事项,翻译不足的处所也迎接随时交换斧正。

原文链接:Webpack2 Migrating
译者:Abcat && 会飞的鱼

resolve.root, resolve.fallback, resolve.modulesDirectories

上述三个选项将被合并为一个范例设置项:resolve.modules. 更多关于resolve的信息信息可查阅 resolving .

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

resolve.extensions

该设置项将不再要求强迫转入一个空字符串,而被修正到了resolve.enforceExtension下, 更多关于resolve的信息信息可查阅 resolving .

resolve.*

更多相干修正和一些不经常运用的设置项在此不一一列举,人人假如在现实项目顶用到可以到resolving 中举行检察.

module.loaders 将变成 module.rules

旧版本中loaders设置项将被功用越发壮大的rules庖代,同时斟酌到新旧版本的兼容,之前旧版本的module.loaders的相干写法照旧有效,loaders中的相干设置项也照旧可以被辨认。

新的loader设置规则会变得越发浅显易用,因而官方也异常引荐用户能实时按module.rules中的相干设置举行调解晋级。

  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

同webpack1.X中相似,loaders继承支撑链式写法,可将相干正则婚配到的文件资本数据在几个loader之间举行同享通报,细致运用说明可见 rule.use

在wepback2中,用户可经由过程use项来指定须要用到的loaders列表(官方引荐),而在weback1中,假如须要设置多个loaders则须要依托简朴的 !符来切分,这类语法出于新旧兼容的斟酌,只会在module.loaders中见效。

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

module称号后自动自动补全 -loader的功用将被移除

在设置loader时,官方不再许可省略-loader扩展名,loader的设置写法大将逐渐趋于严谨。

  module: {
    rules: [
      {
        use: [
-         "style", // 请勿再省略'-loader'
+         "style-loader",
-         "css",
+         "css-loader",
-         "less",
+         "less-loader",
        ]
      }
    ]
  }

固然,假如你想继承坚持之前的省略写法,你写可以在resolveLoader.moduleExtensions中开启默许扩展名设置,不过这类做法并不被引荐。

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

可以从这里检察 #2986 此次变动的缘由;

json-loader 无须要自力装置

当我们须要读取json花样文件时,我们不再须要装置任何loader,webpack2中将会内置 json-loader,自动支撑json花样的读取(喜大普奔啊)。

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

为什么须要默许支撑json花样 官方的诠释是为了在webpack, node.js and browserify三种构建环境下供应无差别的开辟体验。

loader设置项将默许从context中读取

在webpack 1中的一些特别的loader在读取对应资本时,须要经由过程require.resolve指定后才指定见效。从webpack 2后,设置loader在直接从context中举行读取,这就处置惩罚了一些在运用“npm链接”或援用模块以外的context形成的模块反复导入的题目。

设置中可以删除以下代码:

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

module.preLoadersmodule.postLoaders 将被移除

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

之前须要用到preLoader的处所可以改到rules的enfore中举行设置。

UglifyJsPlugin中的 sourceMap设置项将默许封闭

UglifyJsPlugin中的sourceMap 默许项将从 true变成 false

这就意味着当你的js编译紧缩后,须要继承读取原始剧本信息的行数,位置,正告等有效调试信息时,你须要手动开启UglifyJsPlugin 的设置项:sourceMap: true

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

UglifyJsPlugin 的正告设置将默许封闭

UglifyJsPlugin中的 compress.warnings 默许项将从 true变成 false

这就意味着当你想在编译紧缩的时刻检察一部份js的正告信息时,你须要将compress.warnings 手动设置为 true

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

UglifyJsPlugin 不再支撑让 Loaders 最小化文件的情势了

UglifyJsPlugin 将不再支撑让 Loaders 最小化文件的情势。debug 选项已被移除。Loaders 不能从 webpack 的设置中读取到他们的设置项。

loader的最小化文件情势将会在webpack 3或许后续版本中被完全取消掉.

为了兼容部份旧式loader,你可以经由过程 LoaderOptionsPlugin 的设置项来供应这些功用。

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

BannerPlugin 设置项将有所转变

BannerPlugin 将不再许可接收两个参数,而是只供应一个对象设置项

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

OccurrenceOrderPlugin将被内置到场

不须要再针对OccurrenceOrderPlugin举行设置

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

ExtractTextWebpackPlugin 设置项将有所转变

ExtractTextPlugin 1.0.0 在webpack v2将没法运用,你须要从新指定装置ExtractTextPlugin 的webpack2的适配版本.

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

更新后的ExtractTextPlugin版本会针对wepback2举行响应的调解。

ExtractTextPlugin.extract的设置誊写体式格局将调解

module: {
  rules: [
    test: /.css$/,
-    loader: ExtractTextPlugin.extract("style-loader", "css-loader", { publicPath: "/dist" })
+    loader: ExtractTextPlugin.extract({
+      fallbackLoader: "style-loader",
+      loader: "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
+  })
]

全量动态加载资本将默许失效

只要运用一个表达式的资本依靠援用(i. e. require(expr)),如今将建立一个空的context,而不是一个context的完全目次。

当在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将采纳异步式挪用

require.ensureamd require将默许采纳异步的加载体式格局来挪用,而非之前确当模块要求加载完成后再在回调函数中同步触发。

require.ensure将基于原生的Promise对象从新完成,当你在运用 require.ensure 时请确保你的运转环境默许支撑Promise对象,假如缺少则引荐运用装置polyfill.

Loader的设置项将经由过程options来设置

webpack.config.js中将不再许可运用自定义属性来设置loder,这直接带来的一个影响是:在ts设置项中的自定义属性将没法在被在webpack2中准确运用:

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

这是一个异常好的发问,严厉意义上来讲,custom propertyoptions均是用于webpack loader的设置体式格局,从更浅显的说法上看,options应当被称作query,作为一种相似字符串的情势被追加到每一个loader的定名背面,异常相似我们用于url中的查询字符串,但在现实运用中功用要越发壮大

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

options也可作为一个自力的字面对象量,在loader的设置中搭配运用。

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

LoaderOptionsPlugin context

部份loader须要设置context信息, 而且支撑从设置文件中读取。这须要loader经由过程用长选项通报进来,更多loader的明细设置项可以查阅相干文档。

为了兼容部份旧式的loader设置,也可以采纳以下插件的情势来举行设置:

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

debug

debug作为loader中的一个调试情势选项,可以在webpack1的设置中天真切换。在webpack2中,则须要loader经由过程用长选项通报进来,更多loader的明细设置项可以查阅相干文档。

loder的debug情势在webpack3.0或许后续版本中将会被移除。

为了兼容部份旧式的loader设置,也可以采纳以下插件的情势来举行设置:

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

Code Splitting with ES2015

在webpack1中,你须要运用require.ensure完成chunks的懒加载,如:

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

在es2015的 loader中经由过程定义import()作为资本加载要领,当读取到相符ES2015范例的模块时,可完成模块中的内容在运转时动态加载。

webpack在处置惩罚import()时可以完成按需提取开辟中所用到的模块资本,再写入到各个自力的chunk中。webpack2已支撑原生的 ES6 的模块加载器了,这意味着 webpack 2 可以明白和处置惩罚 importexport了。

import()支撑将模块名作为参数相差而且返回一个Promise对象。

function route(path, query) {
  return import(`./routes/${path}/route`)
    .then(route => new route.Route(query));
}
// This creates a separate chunk for each possible route

如许做的另有一个分外的优点就是当我们的模块加载失利时也可以被捕捉到了,由于这些都邑遵照Promise的范例来完成。

值得注意的处所:require.ensure的第三个参数选项许可运用简朴的chunk定名体式格局,然则import API中将不被支撑,假如你愿望继承采纳函数式的写法,你可以继承运用require.ensure

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

(注: System.import将会被弃用,webpack中将不再引荐运用 System.import,官方也引荐运用import举行替代,详见v2.1.0-beta.28

假如想要继承运用Babel中供应的import,你须要自力装置 dynamic-import插件而且挑选babel的Stage 3来捕捉时的毛病, 固然这也可以依据现实情况来操纵而不做强迫束缚。

Dynamic expressions 动态表达式

如今import()中的传参可支撑部份表达式的写法了,假如之前有打仗过CommonJS中require()表达式写法,应当不会对此觉得生疏,(它的操纵实在和 CommonJS 是相似的,给一切可以的文件建立一个环境,当你通报那部份代码的模块还不肯定的时刻,webpack 会自动天生一切可以的模块,然后依据需求加载。这个特征在前端路由的时刻很有效,可以完成按需加载资本)

import() 会针对每一个读取到的module建立自力的separte chunk

function route(path, query) {
  return import(`./routes/${path}/route`)
    .then(route => new route.Route(query));
}
// This creates a separate chunk for each possible route

可以混用 ES2015 和 AMD 和 CommonJS

在 AMD 和 CommonJS 模块加载器中,你可以夹杂运用一切(三种)的模块范例(即使是在同一个文件内里)。

// 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";

注:es2015 balel 的默许预处置惩罚会把 ES6 模块加载器转化成 CommonJS 模块加载。如果想运用 webpack 新增的对原生 ES6 模块加载器的支撑,你须要运用 es2015-webpack 来替代,别的假如你愿望继承运用babel,则须要经由过程设置babel项,使其不会强迫剖析这部份的module symbols以便webpack能准确运用它们,babel的设置以下:

.babelrc

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

Template strings 模板字符串

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"
    }
  ]
}

更多的CLI参数项

以下有更多的CLI 参数项可用:

--define process.env.NODE_ENV="production" 支撑直接设置DefinePlugin.

--display-depth 能显现每一个entry中的module的资本深度

--display-used-exports 能显现每一个module中依靠运用了哪些资本.

--display-max-modules 能限定显现output中援用到的资本数目 (默许显现15个).

-p 指定当前的编译环境为临盆环境,即修正:process.env.NODE_ENV"production"

Cacheable 缓存项

Loaders如今将默许开启资本缓存了,假如你不愿望loader读缓存则须要在设置中指明:

  // Cacheable loader
  module.exports = function(source) {
-   this.cacheable();
    return source;
  }
  // Not cacheable loader
  module.exports = function(source) {
+   this.cacheable(false);
    return source;
  }

Complex options 复合参数项写法

webpack1中的loader参数项中只支撑JSON.stringify-able这类json字符串的写法;

webpack2中的loader参数项中已可以支撑恣意的JS对象的写法了。

运用复合选项时会有一个限定,你须要设置一个ident作为项来保证能准确援用到其他的loader,这意味着经由过程设置我们可以在内联写法中去挪用对应依靠的加载器,以下:

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

{
  test: /.../,
  loader: "...",
  options: {
    ident: "by-ident",
    magic: () => return Math.random()
  }
}

这类写法在寻常开辟顶用的不算多,然则有一种场景下会比较有效,就是当我们的loader须要去天生自力的代码片断时,如,我们在运用style-loader天生一个模块时,须要依靠前面的loader盘算的效果。

// style-loader generated code (simplified)
var addStyle = require("./add-style");
var css = require("-!css-loader?{"modules":true}!postcss-loader??postcss-ident");
addStyle(css);

在这类庞杂选项的运用时ident就有效武之地了。

末端

webpack2无论是从优化资本设置项,到向es6 module,Promise等新范例接轨,再到编译环境和机能的优化,再到API设想的团体范例性上,相对V1的革新照样异常明显的,愿望人人多多尝试,实时反应交换,让webapck的生态圈变得日趋活泼壮大。

    原文作者:Abcat
    原文地址: https://segmentfault.com/a/1190000008181955
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞