【对于《JS高级程序设计》的理解】

  

0配置的局限性

webpack4声称能够0配置,但是0配置有很多局限性,比如只能是单入口的项目,入口和产出的文件名是固定的,entry是src目录下的index.js,产出是dist目录下的main.js,很明显不能满足实际项目应用。于是,开发者还是得自己配置webpack.config.js文件。

  1. null是一个字面量(不是属性),undefined是全局对象的一个属性
  2. typeof null; //object
  3. typeof undefined; //undefined
  4. null === undefined; // false
  5. null == undefined; // true
  6. isNaN(1 + null); //false
  7. isNaN(1 + undefined); //true

 

如何迁移升级到webpack4

所以:

$ node --v8-options | grep harmony

vue-cli项目如何改造

介绍完了webpack4中核心配置项的变化,接下来结合vue-cli示例项目介绍一下,如何配置webpack.conf.js文件。
1.升级npm包版本

建议升级webpack4,同时升级涉及到的loaders和plugins。webpack4 中 cli
工具分离成了 webpack 核心库 与 webpack-cli 命令行工具两个模块,需要使用
CLI ,必安装 webpack-cli 至项目中。

npm i webpack webpack-cli webpack-dev-server -D

涉及到的插件有:

"vue-loader": "^15.0.10",
"vue-style-loader": "^4.1.0",
"vue-template-compiler": "^2.5.16",
"copy-webpack-plugin": "^4.0.1",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"html-webpack-plugin": "^3.1.0",
"optimize-css-assets-webpack-plugin": "^4.0.0",
"webpack-bundle-analyzer": "^2.11.1",
"webpack-dev-middleware": "^3.1.2",
"webpack-dev-server": "^3.1.3",
"webpack-merge": "^4.1.0"

2.修改webpack.base.conf.js

webpack4推荐使用了最新版本的vue-loader(”vue-loader”:
“^15.0.10″),但是最新的vue-loader需要在webapck
config文件中设置VueLoaderPlugin插件,否则会报以下错误:

vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config.

webpack.base.conf.js文件中的改动主要是添加VueLoaderPlugin插件。

const { VueLoaderPlugin } = require('vue-loader');
module.exports = {
    ...
    plugins: [
        // 添加VueLoaderPlugin,以响应vue-loader
        new VueLoaderPlugin()
  ],
    ...
}

3.修改webpack.dev.conf.js

添加mode属性,并设置为development模式;然后注释掉
webpack4开发模式已经内置的插件,如webpack.NamedModulesPluginwebpack.NoEmitOnErrorsPlugin
插件。
图片 1

4.修改webpack.prod.conf.js

添加mode属性,并设置为production模式;然后注释掉
webpack4生产模式已经内置的插件,如CommonsChunkPluginuglifyjs-webpack-plugin
ModuleConcatenationPlugin插件;最后根据webpack4提供的文档配置optimization,使用splitChunksruntimeChunk完成chunk的提取和优化。
图片 2

const webpackConfig = merge(baseWebpackConfig, {
...
    optimization: {
    // 采用splitChunks提取出entry chunk的chunk Group
    splitChunks: {
      cacheGroups: {
        // 处理入口chunk
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          chunks: 'initial',
          name: 'vendors',
        },
        // 处理异步chunk
        'async-vendors': {
          test: /[\\/]node_modules[\\/]/,
          minChunks: 2,
          chunks: 'async',
          name: 'async-vendors'
        }
      }
    },
    // 为每个入口提取出webpack runtime模块
    runtimeChunk: { name: 'manifest' }
  }
...
})

经过以上操作,我们已经基本完成了vue-cli项目的改造。运行项目的时候,注意看控制台的报错,是哪个插件报的错就去升级那个插件,如果存在找不到模块之类的错误就去升级对应的loader。vue-cli项目webapck4下配置demo已经上传到github,欢迎下载。

‘显式地初始化变量依然是明智的选择’这段话是歧义的根源,之前被我理解为,显示地初始化为undefined,这样做导致后面说的就不成立,无论是声明不声明结果还是一样的,因为默认undefined;

ECMAScript 6简介

webpack4中的新特性

webpack3官方发布的时候,提到了下个版本可能的改动点,翻译过来如下所示:

  • 高性能的构建缓存
  • 提升初始化速度和增量构建效率
  • 更好的支持Type Script
  • 修订长期缓存
  • 支持WASM 模块支持
  • 提升用户体验

webpack4官方发布的文档之中主要提及了以下新特性:

  1. String类型:var str = ”;
  2. Number类型:var num = 0;
  3. Boolean类型:var boo = true/false;
  4. Object类型:var obj = {};
  5. 数组:var arr = [];

各大浏览器的最新版本,对 ES6
的支持可以查看kangax.github.io/es5-compat-table/es6/

废弃CommonsChunkPlugin

webpack4废弃了CommonsChunkPlugin,引入了optimization.splitChunksoptimization.runtimeChunk,旨在优化chunk的拆分。先介绍一下code
splitting下的CommonsChunkPlugin有什么缺点,然后仔介绍一下chunk
split是怎么进行优化的。

  • CommonsChunkPlugin的问题

CommmonsChunkPlugin的思路是Create this chunk and move all modules matching minChunks into the new chunk,即将满足minChunks配置想所设置的条件的模块移到一个新的chunk文件中去,这个思路是基于父子关系的,也就是这个新产出的new
chunk是所有chunk的父亲,在加载孩子chunk的时候,父亲chunk是必须要提前加载的。举个例子:

example:
entryA:  vue  vuex  someComponents
entryB:  vue axios someComponents
entryC: vue vux axios someComponents
minchunks: 2 

产出后的chunk:

vendor-chunk:vue vuex axios
chunkA~chunkC: only the components

带来的问题是:对entryA和entryB来说,vendor-chunk都包含了多余的module。
CommonsChunkPlugin另外一个问题是:对异步的模块不友好。下面也举例说明:

example:
entryA:  vue  vuex  someComponents
asyncB:vue axios someComponents
entryC: vue vux axios someComponents
minchunks: 2 

产出后的chunk:

vendor-chunk:vue vuex 
chunkA: only the components
chunkB: vue axios someComponents
chunkC: axios someComponents

带来的问题是:如果asyncB在entryA中动态引入,则会引入多余的module。
总的来说CommonsChunkPlugin有以下三个问题:

  1. 产出的chunk在引入的时候,会包含重复的代码;
  2. 无法优化异步chunk;
  3. 高优的chunk产出需要的minchunks配置比较复杂。
  • SplitChunksPlugin

与CommonsChunkPlugin的父子关系思路不同的是,SplitChunksPlugin引入了chunkGroup的概念,在入口chunk和异步chunk中发现被重复使用的模块,将重叠的模块以vendor-chunk的形式分离出来,也就是vendor-chunk可能有多个,不再受限于是所有chunk中都共同存在的模块,原理的示意如下图所示:
图片 3

其中,可以发现SplitChunksPlugin产出的vendor-chunk有多个,对于入口A来说,引入的代码只有chunkA、vendor-chunkA-B、vendor-chunkA-C、vendor-chunkA-B-C;这时候chunkA、vendor-chunkA-B、vendor-chunkA-C、vendor-chunkA-B-C形成了一个chunkGroup。下面举个列子:

example:
entryA:  vue  vuex  someComponents
entryB:vue axios someComponents
entryC: vue vux axios someComponents

产出后的chunk:

vendor-chunkA-C:vuex 
vendor-chunkB-C:axios
vendor-chunkA-B-C:vue
chunkA: only the components
chunkB: only the components
chunkC: only the components

SplitChunksPlugin能够解决掉CommonsChunkPlugin中提到的三个问题,SplitChunksPlugin在production模式下是默认开启的,但是它默认只作用于异步chunk,如果要作用于入口chunk的话,需要配置optimization.splitChunks.chunks: "all",同时webpack自动split
chunks是有几个限制条件的:

  1. 新产出的vendor-chunk是要被共享的,或者模块来自npm包;
  2. 新产出的vendor-chunk的大小得大于30kb;
  3. 并行请求vendor-chunk的数量不能超出5个;
  4. 对于entry-chunk而言,并行加载的vendor-chunk不能超出3个。

这些限制可以在SplitChunks的默认配置项中可以一一对应的看到。

splitChunks: {
    chunks: "async",
    minSize: 30000,
    minChunks: 1,
    maxAsyncRequests: 5,
    maxInitialRequests: 3,
    name: true,
    cacheGroups: {
        default: {
            minChunks: 2,
            priority: -20
            reuseExistingChunk: true,
        },
        vendors: {
            test: /[\\/]node_modules[\\/]/,
            priority: -10
        }
    }
}

其实不难理解这些限制,因为SplitChunksPlugin产生的结果就是原来chunk被拆分了,引入的文件数量会变多,因此需要在文件数量上进行限制。

  • runtimeChunkPlugin

在使用CommonsChunkPlugin的时候,我们通常会把webpack
runtime的基础函数提取出来,单独作为一个chunk,毕竟code
splitting想把不变的代码单独抽离出来,方便浏览器缓存,提升加载速度。webpack4废弃了CommonsChunkPlugin,采用了runtimeChunkPlugin可以将每个entry
chunk中的runtime部分的函数分离出来,只需要一个简单的配置:optimization.runtimeChunk: true

意思就是,使用变量的时候,要对变量进行初始化一个非undefined的值,这样后面我们在用typeof进行检测,只要返回undefined就认为是未声明的变量是成立的

Node 是 JavaScript 的服务器运行环境(runtime)。

webpack4在2月底的时候发布,这次webpack4有了一个名字”Legato”,也就是”连奏”的意思,寓意webpack在不断进化,而且是无缝(no-gaps)的进化。webpack的进化点是通过捐赠者和用户投票来决定的,之前在介绍webpack3的时候,曾给出过投票数在前几名的优化点,集中在用户体验、构建性能(速度和产出大小)、通用和适配性(es
module、typescript、web
assemble)等。webpack4发布了,下面将结合文档和实践,验证一下webpack是否兑现了当初的诺言。

发表评论

电子邮件地址不会被公开。 必填项已用*标注