金沙棋牌官方平台

当前位置:金沙棋牌 > 金沙棋牌官方平台 > 构建打包优化,配置最佳实践

构建打包优化,配置最佳实践

来源:http://www.logblo.com 作者:金沙棋牌 时间:2019-11-21 10:22

Webpack 4 配置最棒奉行

2018/06/22 · JavaScript · webpack

原来的小讲出处: Zindex   

Webpack 4 发表已经有大器晚成段时间了。Webpack 的版本号已经光临了 4.12.x。但因为 Webpack 官方还从未实现搬迁指南,在文书档案层面上还装有欠缺,当先四分之几人对进步 Webpack 照旧稀里糊涂。

只是 Webpack 的支付协会已经写了生机勃勃部分碎片的篇章,官互连网也会有了新版配置的文书档案。社区中有的开垦者也已经成功试水,进级到了 Webpack 4,况兼总计成了博客。所以小编也算是去打听了 Webpack 4 的具体景况。以下正是自家对搬迁到 Webpack 4 的有些资历。

正文的显要在:

  • Webpack 4 在安排上带给了怎么惠及?要搬迁需求改革配置文件的什么内容?
  • 在此之前的 Webpack 配置最好实行在 Webpack 4 那几个版本,还适用吗?

浅谈React + Webpack 创设打包优化,reactwebpack

本文介绍了React + Webpack 营造打包优化,分享给大家,具体如下:

使用 babel-react-optimize 对 React 代码实行优化

检查未有选择的库,去除 import 援引

按需打包所用的类库,比如 lodash 、 echart 等

lodash 能够使用babel-plugin-lodash 举办优化。

亟需小心的是

在 babel-react-optimize 中动用了 babel-plugin-transform-react-remove-prop-types 这些插件。平常状态下,假使您在代码中尚无援引到零器件的 PropTypes ,则一心没难题。要是您的构件用到了,那么使用该插件大概会促成难点。

具体见:

Webpack 营造打包优化

Webpack 营造打包存在的标题首要性集聚于上边多少个地点:

  1. Webpack 营造速度慢
  2. Webpack 打包后的文本容积过大

Webpack 创设速度慢

能够选拔 Webpack.DDLPlugin , HappyPack 来压实创设速度。具体参见小铭在 DMP DDLPlugin 的文书档案。原来的作品如下:

Webpack.DLLPlugin

增加一个 webpack.dll.config.js
首借使用到三个 DllPlugin 插件,把一些第三方的能源独立包装,同不常候停放三个manifest.json 配置文件中,

与此相类似在组件中更新后,就不会再也 build 那么些第三方的能源,

  1. 与此同期独立安排 dll/vendors.js 文件,提要求 webpack.dll.config.js
  2. 修改 package.json

在 scripts 中添加: "dll": "webpack --config webpack.dll.config.js --progress --colors ", 。

施行 npm run dll 今后,会在 dll 目录下生产 多少个文件 vendor-manifest.json ,vendor.dll.js

配置 webpack.dev.config.js 文件,参与二个 DllReferencePlugin 插件,并点名 vendor-manifest.json 文件

new webpack.DllReferencePlugin({
 context: join(__dirname, 'src'),
 manifest: require('./dll/vendor-manifest.json')
})

修改 html

<% if(htmlWebpackPlugin.options.NODE_ENV ==='development'){ %>
 <script src="dll/vendor.dll.js"></script>
<% } %>

只顾,须要在 htmlWebpackPlugin 插件中布置 NODE_ENV 参数

Happypack

经过二十四线程,缓存等措施升高 rebuild 功效

在 webpack.dev.config.js 中针对不一样的能源成立八个 HappyPack, 比如 js 1 个,less 1 个,并设置好 id

new HappyPack({
 id: 'js',
 threadPool: happyThreadPool,
 cache: true,
 verbose: true,
 loaders: ['babel-loader?babelrc&cacheDirectory=true'],
}),
new HappyPack({
 id: 'less',
 threadPool: happyThreadPool,
 cache: true,
 verbose: true,
 loaders: ['css-loader', 'less-loader'],
})

在 module.rules 中配置 use 为 happypack/loader, 设置 id

{
 test: /.js$/,
 use: [
 'happypack/loader?id=js'
 ],
 exclude: /node_modules/
}, {
 test: /.less$/,
 loader: extractLess.extract({
 use: ['happypack/loader?id=less'],
 fallback: 'style-loader'
 })
}

减掉 Webpack 打包后的文本容量大小

率先须求对我们整个 bundle 举办解析,由什么东西组成及各组成部分所占大小。

此处推荐 webpack-bundle-analyzer 。安装后在 webpack.dev.config.js 中增加插件就能够,就会在每一回运维后活动在网址展开深入分析结果,如下图

plugins.push( new BundleAnalyzerPlugin());

金沙棋牌官方平台 1

除了那个之外,还是能够将包裹进程输出成json文件

webpack --profile --json -> stats.json

然后到上面那四个网址实行剖判

  1. webpack/analyse
  2. Webpack Chart

透过地点的图纸剖析能够知晓得看看,整个 bundle.js 的组成都部队分及相应的分寸。

缓慢解决 bundle.js 体量过大的消除思路如下:

  1. 坐蓐景况启用压缩等插件,去除不要求插件
  2. 拆分业务代码与第三方库及国有模块
  3. webpack 开启 gzip 压缩
  4. 按需加载

接续后代遭逢启用压缩等插件,去除无需插件

承保在生育条件运转 webpack.DefinePlugin 和 webpack.optimize.UglifyJsPlugin 。

const plugins = [
 new webpack.DefinePlugin({
  'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')
 }),
  new webpack.optimize.UglifyJsPlugin({
  compress: {
   warnings: false,
   drop_console: false //eslint-disable-line
  }
  })   
]

拆分业务代码与第三方库及公共模块

是因为品种的工作代码更换频率相当的高,而第三方库的代码变化则相对未有那么频率。假使将业务代码和第三库打包到同贰个chunk 的话,在历次营造的时候,哪怕业务代码只改了风流洒脱行,尽管第三方库的代码未有爆发变化,会引致整个 chunk 的 hash 跟上一遍分歧。那不是大家想要的结果。我们想要的是,假设第三方库的代码没有生成,那在创设的时候也要保管相应的 hash 未有发生变化,进而能利用浏览器缓存,越来越好的增高页面加载品质和抽水页面加载时间。

据此得以将第三库的代码单独拆分成 vendor chunk,与业务代码抽离。那样固然业务代码再怎么产生变化,只要第三方库代码未有发生变化,对应的 hash 就不变。

先是 entry 配置七个 app 和 vendor 多个chunk

entry: {
 vendor: [path.join(__dirname, 'dll', 'vendors.js')],
 app: [path.join(__dirname, 'src/index')]
},
output: {
 path: path.resolve(__dirname, 'build'),
 filename: '[name].[chunkhash:8].js'
},

内部 vendros.js 是本人定义的哪些第三方库须要放入 vendor 中,如下:

require('babel-polyfill');
require('classnames');
require('intl');
require('isomorphic-fetch');
require('react');
require('react-dom');
require('immutable');
require('redux');

接下来经过 CommonsChunkPlugin 拆分第三库

plugins.push(
 // 拆分第三方库
 new webpack.optimize.CommonsChunkPlugin({ name: 'vendor' }),
 // 拆分 webpack 自身代码
 new webpack.optimize.CommonsChunkPlugin({
  name: 'runtime',
  minChunks: Infinity
 })
);

下面的配备有五个细节供给介怀

  1. 使用 chunkhash 而不用 hash
  2. 单身拆分 webpack 自个儿代码

使用 chunkhash 而不用 hash

先来探望那二者有什么差异:

  1. hash 是 build-specific ,任何多少个文书的转移都会引致编写翻译的结果分化,适用于开辟阶段
  2. chunkhash 是 chunk-specific ,是基于各类 chunk 的内容总计出的 hash,适用于临盆

据此为了确定保障第三方库不改变的场地下,对应的 vendor.js 的 hash 也要保持不改变,大家再 output.filename 中应用了 chunkhash

单身拆分 webpack 本身代码

Webpack 有个已知难题:

webpack 自己的 boilerplate 和 manifest 代码恐怕在历次编写翻译时都会扭转。

那招致我们只是在 入口文件 改了一整套代码,但编写翻译出的 vendor 和 entry chunk 都变了,因为它们自个儿都包罗那生龙活虎部分代码。

那是不创造的,因为实在大家的第三方库的代码没变,vendor 不应有在我们职业代码变化时发生变化。

为此大家必要将 webpack 那部分代码抽离抽离

new webpack.optimize.CommonsChunkPlugin({
   name: "runtime",
   minChunks: Infinity
}),

其间的 name 只要不在 entry 就能够,平常使用 "runtime" 或 "manifest" 。

除此以外三个参数 minChunks 表示:在扩散公共chunk(commons chunk) 早前所急需包蕴的起码数量的 chunks。数量必需大于等于2,只怕简单等于 chunks的数额,传入 Infinity 会立刻生成 公共chunk,但里面未有模块。

更多关于 CommonChunkPlugin 能够查阅 官方文书档案

拆分公共财富

同 上边的拆分第三方库相通,拆分公共能源能够将公用的模块单独打出一个chunk,你能够安装 minChunk 来筛选是共用有些次模块才将它们分离。配置如下:

new webpack.optimize.CommonsChunkPlugin({
 name: 'common',
 minChunks: 2,
}),

是还是不是供给展开这一步优化能够自行根据项目标作业复开支来剖断。

金沙棋牌官方平台,开启 gzip

使用 CompressionPlugin 插件开启 gzip 就能够:

// 添加 gzip
new CompressionPlugin({
 asset: '[path].gz[query]',
 algorithm: 'gzip',
 test: /.(js|html)$/,
 threshold: 10240,
 minRatio: 0.8
})

上述正是本文的全部内容,希望对我们的上学抱有助于,也冀望我们多都赐教帮客之家。

+ Webpack 创设打包优化,reactwebpack 本文介绍了React + Webpack 营造打包优化,分享给我们,具体如下: 使用 babel-react-optimize 对 React 代...

var path = require('path')
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var HtmlWebpackPlugin = require('html-webpack-plugin')

Webpack 4 事先的 Webpack 最好施行

这里以 Vue 官方的 Webpack 模板 vuejs-templates/webpack 为例,说说 Webpack 4 事先,社区里相比早熟的 Webpack 配置文件是何许组织的。

// 用于从webpack生成的bundle中提取文本到一定文件中的插件
// 能够收抽取css,js文件将其与webpack输出的bundle抽离

分化开拓和分娩境遇

大致的目录结构是那样的:

+ build + config + src

1
2
3
+ build
+ config
+ src

在 build 目录下有多个 webpack 的布局。分别是:

  • webpack.base.conf.js
  • webpack.dev.conf.js
  • webpack.prod.conf.js
  • webpack.test.conf.js

那分别对应付出、分娩和测验意况的布署。此中 webpack.base.conf.js 是一些国有的陈设项。大家使用 webpack-merge 把那些公共配置项和遭逢特定的配备项 merge 起来,成为一个全部的铺排项。例如 webpack.dev.conf.js 中:

'use strict' const merge = require('webpack-merge') const baseWebpackConfig = require('./webpack.base.conf') const devWebpackConfig = merge(baseWebpackConfig, { ... })

1
2
3
4
5
6
7
'use strict'
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
 
const devWebpackConfig = merge(baseWebpackConfig, {
   ...
})

那七个条件不唯有有意气风发对配备区别,更关键的是,每一个配置中用 webpack.DefinePlugin 向代码注入了 NODE_ENV 这几个情况变量。

以此变量在分歧境况下有分歧的值,譬喻 dev 景况下正是development。这一个意况变量的值是在 config 文件夹下的安插文件中定义的。Webpack 首先从布置文件中读取那些值,然后注入。比方那样:

build/webpack.dev.js

plugins: [ new webpack.DefinePlugin({ 'process.env': require('../config/dev.env.js') }), ]

1
2
3
4
5
plugins: [
  new webpack.DefinePlugin({
    'process.env': require('../config/dev.env.js')
  }),
]

config/dev.env.js

module.exports ={ NODE_ENV: '"development"' }

1
2
3
module.exports ={
  NODE_ENV: '"development"'
}

至于差异景况下情况变量具体的值,比方开拓条件是 development,临蓐条件是 production,其实是大家蔚然成风的。

框架、库的小编,只怕是我们的事体代码里,都会有局地基于条件做决断,试行区别逻辑的代码,比方那样:

if (process.env.NODE_ENV !== 'production') { console.warn("error!") }

1
2
3
if (process.env.NODE_ENV !== 'production') {
  console.warn("error!")
}

那个代码会在代码压缩的时候被预施行壹遍,然后风度翩翩旦条件表明式的值是 true,那这些 true 分支里的内容就被移除了。那是风华正茂种编写翻译时的死代码优化。这种差别不一样的条件,并给意况变量设置区别的值的实施,让大家打开了编写翻译时按意况对代码进行针对优化的只怕。

var ExtractTextPlugin = require('extract-text-webpack-plugin')

Code Splitting && Long-term caching

Code Splitting 通常必要做那个事情:

  • 为 Vendor 单独包装(Vendor 指第三方的库只怕国有的底工零件,因为 Vendor 的转移少之又少,单独打包利于缓存卡塔 尔(阿拉伯语:قطر‎
  • 为 Manifest (Webpack 的 Runtime 代码卡塔尔单独包装
  • 为分裂入口的公家事务代码打包(同理,也是为了缓存和加载速度卡塔 尔(英语:State of Qatar)
  • 为异步加载的代码打二个共用的包

Code Splitting 平日是经过布置 CommonsChunkPlugin 来完结的。叁个天下第一的配备如下,分别为 vendor、manifest 和 vendor-async 配置了 CommonsChunkPlugin。

new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', minChunks (module) { return ( module.resource && /.js$/.test(module.resource) && module.resource.indexOf( path.join(__dirname, '../node_modules') ) === 0 ) } }), new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', minChunks: Infinity }), new webpack.optimize.CommonsChunkPlugin({ name: 'app', async: 'vendor-async', children: true, minChunks: 3 }),

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks (module) {
        return (
          module.resource &&
          /.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, '../node_modules')
          ) === 0
        )
      }
    }),
 
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      minChunks: Infinity
    }),
 
    new webpack.optimize.CommonsChunkPlugin({
      name: 'app',
      async: 'vendor-async',
      children: true,
      minChunks: 3
    }),

CommonsChunkPlugin 的特点就是布局相比较难懂,我们的计划往往是复制过来的,那么些代码基本上成了模版代码(boilerplate卡塔 尔(阿拉伯语:قطر‎。倘诺Code Splitting 的须要归纳倒好,要是有比较卓绝的渴求,比方把分裂入口的 vendor 打区别的包,那就很难安顿了。总之配置 Code Splitting 是八个比较痛楚的工作。

而 Long-term caching 战略是如此的:给静态文件多个非常短的缓存过期时刻,比方一年。然后在给文件名里加上一个hash,每一次创设时,当文件内容改变时,文件名中的 hash 也会改动。浏览器在依据文件名作为文件的标记,所以当 hash 改换时,浏览器就能另行加载这几个文件。

Webpack 的 Output 选项中能够配备文件名的 hash,举个例子那样:

output: { path: config.build.assetsRoot, filename: utils.assetsPath('js/[name].[chunkhash].js'), chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') },

1
2
3
4
5
output: {
  path: config.build.assetsRoot,
  filename: utils.assetsPath('js/[name].[chunkhash].js'),
  chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},

var env = process.env.NODE_ENV === 'testing'
? require('../config/test.env')
: config.build.env

Webpack 4 下的特等推行

// 合併功底的webpack配置
var webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true
})
},

Webpack 4 的变与不变

Webpack 4 那个版本的 API 有部分 breaking change,但不表示说这几个本子就发生了倾覆的改换。其实变化的点独有几个。况且风度翩翩旦您精心询问了这一个变迁,你势必会大快人心。

搬迁到 Webpack 4 也只需求检查一下 checklist,看看那几个点是不是都覆盖到了,就足以了。

devtool: config.build.productionSourceMap ? '#source-map' : false,
// 配置webpack的输出
output: {
// 编写翻译输出目录
path: config.build.assetsRoot,
// 编写翻译输出文件名格式
filename: utils.assetsPath('js/[name].[chunkhash].js'),
// 未有一点点名输著名的文书输出的文本名格式
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},

支付和生育情状的分化

Webpack 4 引入了 mode 那么些选项。那个选项的值能够是 development 或许 production。

安装了 mode 之后会把 process.env.NODE_ENV 也设置为 development 或者production。然后在 production 情势下,会暗中认可开启 UglifyJsPlugin 等等一群插件。

Webpack 4 补助零配置利用,可以从命令行内定 entry 的职位,如果不点名,正是 src/index.js。mode 参数也足以从命令行参数字传送入。那样有个别常用的生育遭受打包优化都得以一向启用。

咱俩供给静心,Webpack 4 的零配置是有限度的,要是要增加自身想加的插件,或许要加多少个entry,依然供给叁个铺排文件。

固然这么,Webpack 4 在种种方面都做了大力,努力让零配置能够做的事情越来越多。这种内置优化的秘技使得我们在项目运行的时候,能够把入眼精力放在工効耗费上,等中期业务变复杂过后,才须要关心配置文件的编辑。

在 Webpack 4 推出 mode 那么些选项早前,若是想要为差别的支付条件创设分裂的营造选项,我们只可以通过建立五个Webpack 配置且分别设置分歧的条件变量值这种方法。那也是社区里的最好实行。

Webpack 4 推出的 mode 选项,其实是生龙活虎种对社区中精品推行的收受。这种思路笔者是很同情的。开源项目来自于社区,在社区中成长,从社区中接到甲状腺素,然后回报社区,那是贰个良性循环。近年来本人在广大前端项目中都观看了近乎的趋势。接下来要讲的别的几个Webpack 4 的特征也是和社区的报告离不开的。

那么上文中介绍的应用八个 Webpack 配置,以致手动情状变量注入的不二诀窍,是还是不是在 Webpack 4 下就不适用了啊?其实不然。在Webpack 4 下,对于二个庄严的品种,我们依然亟待多少个不等的配备文件。假使大家对为测验情状的打包做一些独特管理,我们还须求在丰盛配置文件里用 webpack.DefinePlugin 手动注入 NODE_ENV 的值(比如 test)。

Webpack 4 下假设必要二个 test 碰着,那 test 景况的 mode 也是 development。因为 mode 唯有付出和生产两种,测量试验景况应该是归属开采阶段。

// 配置webpack插件

其三方库 build 的接受

在 Webpack 3 一代,大家须要在生养条件的的 Webpack 配置里给第三方库设置 alias,把那一个库的门道设置为 production build 文件的路径。以此来引进临蓐版本的依据。

譬如说那样:

resolve: { extensions: [".js", ".vue", ".json"], alias: { vue$: "vue/dist/vue.runtime.min.js" } },

1
2
3
4
5
6
resolve: {
  extensions: [".js", ".vue", ".json"],
  alias: {
    vue$: "vue/dist/vue.runtime.min.js"
  }
},

在 Webpack 4 引进了 mode 之后,对于一些注重,大家可以不要配置 alias,比方 React。React 的输入文件是这么的:

'use strict'; if (process.env.NODE_ENV === 'production') { module.exports = require('./cjs/react.production.min.js'); } else { module.exports = require('./cjs/react.development.js'); }

1
2
3
4
5
6
7
'use strict';
 
if (process.env.NODE_ENV === 'production') {
  module.exports = require('./cjs/react.production.min.js');
} else {
  module.exports = require('./cjs/react.development.js');
}

那样就达成了 0 配置活动选取生产 build。

但超越46%的第三库并不曾做那么些进口的条件判别。所以这种场所下我们仍然必要手动配置 alias。

plugins: [
//
new webpack.DefinePlugin({
'process.env': env
}),

Code Splitting

Webpack 4 下还恐怕有二个大转移,正是打消了 CommonsChunkPlugin,引进了 optimization.splitChunks 这一个选项。

optimization.splitChunks 暗许是不用安装的。假使 mode 是 production,那Webpack 4 就能够张开 Code Splitting。

暗许 Webpack 4 只会对按需加载的代码做分割。假若我们要求配备初始加载的代码也出席到代码分割中,能够设置 splitChunks.chunks 为 ‘all’。

Webpack 4 的 Code Splitting 最大的天性就是安插简单(0配置起步卡塔尔国,和听他们说内置准则自动拆分。内置的代码切分的平整是如此的:

  • 新 bundle 被四个及以上模块引用,只怕来自 node_modules
  • 新 bundle 大于 30kb (压缩早先卡塔尔国
  • 异步加载并发加载的 bundle 数不能够超过 5 个
  • 起来加载的 bundle 数不可能压倒 3 个

轻巧易行的说,Webpack 会把代码中的公共模块自动抽出来,产生四个包,前提是那一个包大于 30kb,不然Webpack 是不会挤出公共代码的,因为扩展一遍呼吁的资产是不可能忽略的。

实际的事情场景下,具体的拆分逻辑,能够看 SplitChunksPlugin 的文档以及 webpack 4: Code Splitting, chunk graph and the splitChunks optimization 这篇博客。这两篇小说基本陈列了全数望现身的境况。

设倘诺平常的应用,Webpack 4 内置的家有家规就丰裕了。

假定是例外的须求,Webpack 4 的 optimization.splitChunks API也能够满意。

splitChunks 有一个参数叫 cacheGroups,那些参数相似事先的 CommonChunks 实例。cacheGroups 里每一个对象正是一个客户定义的 chunk。

事先大家讲到,Webpack 4 内置有黄金时代套代码分割的不成方圆,这顾客也足以自定义 cacheGroups,相当于自定义 chunk。那多少个 module 应该被抽到哪些 chunk 呢?那是由 cacheGroups 的收取范围调整的。每一种 cacheGroups 都足以定义本人收取模块的限定,也等于怎样文件中的公共代码会抽出到温馨这个chunk 中。不相同的 cacheGroups 之间的模块范围假诺有混合,大家能够用 priority 属性调整优先级。Webpack 4 暗中认可的抽出的优先级是最低的,所以模块会预先被抽出到客商的自定义 chunk 中。

splitChunksPlugin 提供了二种调控 chunk 收取模块范围的法门。风华正茂种是 test 属性。这些天性能够流传字符串、正则恐怕函数,全部的 module 都会去相称test 传入的口径,若是基准相符,就被归入这几个 chunk 的备选模块范围。如若我们传入的标准是字符串恐怕正则,那相称的流水线是如此的:首先匹配module 的门路,然后匹配 module 以前所在 chunk 的 name。

诸如我们想把富有 node_modules 中引进的模块打包成叁个模块:

vendors1: { test: /[/]node_modules[/]/, name: 'vendor', chunks: 'all', }

1
2
3
4
5
  vendors1: {
    test: /[/]node_modules[/]/,
    name: 'vendor',
    chunks: 'all',
  }

因为从 node_modules 中加载的依据路线中都带有 node_modules,所以这几个正则会同盟全体从 node_modules 中加载的依据。

test 属性能够以 module 为单位调节 chunk 的收取范围,是意气风发种细粒度超小的法子。splitChunksPlugin 的第三种调整收取模块范围的办法便是 chunks 属性。chunks 能够是字符串,比如 ‘all’|’async’|’initial’,分别代表了全部chunk,按需加载的 chunk 以至起首加载的 chunk。chunks 也足以是贰个函数,在这里个函数里大家得以拿到chunk.name。那给了我们通过输入来划分代码的力量。那是意气风发种细粒度非常大的艺术,以 chunk 为单位。

举个例证,比如大家有 a, b, c 三个输入。大家盼望 a,b 的集体代码单独打包为 common。相当于说 c 的代码不到场国有代码的细分。

作者们能够定义三个 cacheGroups,然后设置 chunks 属性为八个函数,那些函数担任过滤这些 cacheGroups 包涵的 chunk 是如何。示例代码如下:

optimization: { splitChunks: { cacheGroups: { common: { chunks(chunk) { return chunk.name !== 'c'; }, name: 'common', minChunks: 2, }, }, }, },

1
2
3
4
5
6
7
8
9
10
11
12
13
  optimization: {
    splitChunks: {
      cacheGroups: {
        common: {
          chunks(chunk) {
            return chunk.name !== 'c';
          },
          name: 'common',
          minChunks: 2,
        },
      },
    },
  },

地点配置的情趣正是:大家想把 a,b 入口中的公共代码单独打包为八个名字为common 的 chunk。使用 chunk.name,大家得以轻便的完成这么些需要。

在地点的状态中,大家清楚 chunks 属性能够用来按入口切分几组公共代码。今后大家来看二个稍微复杂一些之处:对两样分组入口中引进的 node_modules 中的依赖进行分组。

比方说我们有 a, b, c, d 三个输入。我们盼望 a,b 的依靠打包为 vendor1,c, d 的依赖性打包为 vendor2。

其风流倜傥需要要求大家对进口和模块都做过滤,所以大家须要接收 test 属性那几个细粒度非常小的方式。大家的思路正是,写多个 cacheGroup,一个cacheGroup 的判别标准是:固然 module 在 a 大概 b chunk 被引进,並且module 的门径包括 node_modules,那这些 module 就应有被打包到 vendors1中。 vendors2 同理。

vendors1: { test: module => { for (const chunk of module.chunksIterable) { if (chunk.name && /(a|b)/.test(chunk.name)) { if (module.nameForCondition() && /[/]node_modules[/]/.test(module.nameForCondition())) { return true; } } } return false; }, minChunks: 2, name: 'vendors1', chunks: 'all', }, vendors2: { test: module => { for (const chunk of module.chunksIterable) { if (chunk.name && /(c|d)/.test(chunk.name)) { if (module.nameForCondition() && /[/]node_modules[/]/.test(module.nameForCondition())) { return true; } } } return false; }, minChunks: 2, name: 'vendors2', chunks: 'all', }, };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  vendors1: {
    test: module => {
      for (const chunk of module.chunksIterable) {
            if (chunk.name && /(a|b)/.test(chunk.name)) {
                if (module.nameForCondition() && /[/]node_modules[/]/.test(module.nameForCondition())) {
                 return true;
             }
            }
       }
      return false;
    },
    minChunks: 2,
    name: 'vendors1',
    chunks: 'all',
  },
  vendors2: {
    test: module => {
      for (const chunk of module.chunksIterable) {
            if (chunk.name && /(c|d)/.test(chunk.name)) {
                if (module.nameForCondition() && /[/]node_modules[/]/.test(module.nameForCondition())) {
                 return true;
             }
            }
       }
      return false;
    },
    minChunks: 2,
    name: 'vendors2',
    chunks: 'all',
  },
};

// 丑化压缩代码
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
sourceMap: true
}),

Long-term caching

Long-term caching 这里,基本的操作和 Webpack 3 是黄金时代致的。可是 Webpack 3 的 Long-term caching 在操作的时候,有个小意思,这几个题目是有关 chunk 内容和 hash 变化不近似的:

在公共代码 Vendor 内容不改变的意况下,增多 entry,大概 external 重视,也许异步模块的时候,Vendor 的 hash 会退换

早先 Webpack 官方的专栏里面有大器晚成篇小说讲这一个主题材料:Predictable long term caching with Webpack。给出了二个建设方案。

其一方案的中坚就是,Webpack 内部维护了叁个自增的 id,每一个 chunk 都有二个id。所以当扩张 entry 只怕此外项目 chunk 的时候,id 就能够转移,招致内容未有生成的 chunk 的 id 也爆发了变化。

对此大家的答应方案是,使用 webpack.NamedChunksPlugin 把 chunk id 变为叁个字符串标记符,那个字符包日常就是模块的相对路线。那样模块的 chunk id 就能够牢固下来。

金沙棋牌官方平台 2

这里的 vendors1 就是 chunk id

HashedModuleIdsPlugin 的坚决守护和 NamedChunksPlugin 是风姿洒脱律的,只不过 HashedModuleIdsPlugin 把依据模块相对路线生成的 hash 作为 chunk id,那样 chunk id 会更加短。因而在生育中更推荐用 HashedModuleIdsPlugin。

这篇小说说还讲到,webpack.NamedChunksPlugin 只可以对不感到奇的 Webpack 模块起效率,异步模块,external 模块是不会起效果的。

异步模块能够在 import 的时候增加 chunkName 的注释,比方那样:import(/ webpackChunkName: “lodash” / ‘lodash’).then() 那样就有 Name 了

所以我们要求再利用贰个插件:name-all-modules-plugin

其后生可畏插件中用到有的老的 API,Webpack 4 会发出警告,这些 pr 有新的本子,但是笔者不自然会 merge。我们利用的时候可以直接 copy 这些插件的代码到大家的 Webpack 配置内部。

做了那些工作未来,大家的 Vendor 的 ChunkId 就再也不会发生不应该产生的浮动了。

 

总结

Webpack 4 的改良首假使对社区中最好试行的选择。Webpack 4 经过新的 API 大大晋级了 Code Splitting 的心得。但 Long-term caching 中 Vendor hash 的标题如故还未有减轻,须要手动配置。本文首要介绍的正是 Webpack 配置最好试行在 Webpack 3.x 和 4.x 背景下的异同。希望对读者的 Webpack 4 项指标安顿文件协会有所补助。

另外,推荐 SURVIVEJS – WEBPACK 那些在线教程。那一个课程总括了 Webpack 在实际上付出中的实践,何况把材质更新到了流行的 Webpack 4。

1 赞 4 收藏 评论

金沙棋牌官方平台 3

// 抽离css文件
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css')
}),

 

// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see
new HtmlWebpackPlugin({
filename: process.env.NODE_ENV === 'testing'

? 'index.html'
: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
//
},

// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),

// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module, count) {
// any required modules inside node_modules are extracted to vendor

return (
module.resource &&
/.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated

new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
chunks: ['vendor']
})
]
})

// gzip格局下供给引进compression插件进行减少
if (config.build.productionGzip) {
var CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),

threshold: 10240,
minRatio: 0.8
})
)
}

if (config.build.bundleAnalyzerReport) {
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig

本文由金沙棋牌发布于金沙棋牌官方平台,转载请注明出处:构建打包优化,配置最佳实践

关键词: