css的处理:
1 css在dev环境下,可以打包在 html的 style中
{ test: /.css$/, // loader 的执行顺序是:从后往前 loader: ['style-loader', 'css-loader', 'postcss-loader'] // 加了 postcss }
2. css在build线上环境下,要单独抽离出来,
module:{ rules:[ { // 抽离 css { test: /.css$/, loader: [ MiniCssExtractPlugin.loader, // 注意,这里不再用 style-loader 'css-loader', 'postcss-loader' ] } } ] }, plugins: [ // 抽离 css 文件 new MiniCssExtractPlugin({ filename: 'css/main.[contentHash:8].css' }) ], optimization: { // 压缩 css minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})], }
提取公共代码chunk块的技术:splitChunks 分割代码块 和使用dll 打包公共代码块 虽然都可以提取公共代码,但是 splitChunks 会在每次webpack 打包的时候 都要执行 而使用 dll打包之后 只需要打包一次。
splitChunks: { chunks: 'all', // 缓存分组 cacheGroups: { // 第三方模块 vendor: { name: 'vendor', // chunk 名称 priority: 1, // 权限更高,优先抽离,重要!!! test: /node_modules/, minSize: 0, // 大小限制 minChunks: 1 // 最少复用过几次 }, // 公共的模块 common: { name: 'common', // chunk 名称 priority: 0, // 优先级 minSize: 0, // 公共模块的大小限制 minChunks: 2 // 公共模块最少复用过几次 } } }
对应的html中也要引入该trunk
// 多入口 - 生成 index.html new HtmlWebpackPlugin({ template: path.join(srcPath, 'index.html'), filename: 'index.html', // chunks 表示该页面要引用哪些 chunk (即上面的 index 和 other),默认全部引用 chunks: ['index', 'vendor', 'common'] // 要考虑代码分割 }),
但是在最新的 HtmlWebpackPlugin 中已经自动引入了 代码分割的 代码 ,无需在chunks 中手动引入。
-------
配置react环境: https://www.babeljs.cn/docs/babel-preset-react
jsx使用babel的loader,并且配置config环境:
{ "presets": ["@babel/preset-react"] }
-- module 各个源码文件,webpack中一切皆为模块,比如 js、css、image 等import引入的文件
-- chunk理解为“代码块”,多模块合成的,包含了很多代码块的汇总。比如:entry中的js汇总后的文件(也就是打包后的js文件,比如包含了多个js文件,自定义splitChunks),chunk可以理解为内存中的一个概念还没有输出。
-- bundle理解则可理解为已打包好的代码包,最终输出文件。就像vue-cli中build后会输出一个vender.js,这个js就是代码包了;
------------------
webpack 性能优化-构建速度
1. 优化babel-loader
2. ingnorePlugin
3. noParse
4.happyPack
5. ParallelUglifyPlugin
6. 自动刷新
7. 热更新
8. DllPlugin
2. IngorePlugin: https://blog.csdn.net/qq_17175013/article/details/86845624
3. noParse
这是module中的一个属性,作用:
不去解析属性值代表的库的依赖
module:{ noParse:/jquery/,//不去解析jquery中的依赖库 rules:[ { //... } ] }
4.happyPack,开启多进程打包
// js { test: /.js$/, // 把对 .js 文件的处理转交给 id 为 babel 的 HappyPack 实例 use: ['happypack/loader?id=babel'], include: srcPath, // exclude: /node_modules/ } plugins:[ // happyPack 开启多进程打包 new HappyPack({ // 用唯一的标识符 id 来代表当前的 HappyPack 是用来处理一类特定的文件 id: 'babel', // 如何处理 .js 文件,用法和 Loader 配置中一样 loaders: ['babel-loader?cacheDirectory'] }) ]
5. ParallelUglifyPlugin,使用 ParallelUglifyPlugin 并行压缩输出的 JS 代码
// 使用 ParallelUglifyPlugin 并行压缩输出的 JS 代码 new ParallelUglifyPlugin({ // 传递给 UglifyJS 的参数 // (还是使用 UglifyJS 压缩,只不过帮助开启了多进程) uglifyJS: { output: { beautify: false, // 最紧凑的输出 comments: false, // 删除所有的注释 }, compress: { // 删除所有的 `console` 语句,可以兼容ie浏览器 drop_console: true, // 内嵌定义了但是只用到一次的变量 collapse_vars: true, // 提取出出现多次但是没有定义成变量去引用的静态值 reduce_vars: true, } } })
关于开启多进程:
1. 项目较大,打包较慢,开启多进程能提高速度;
2.项目较小,打包很快,开启后会降低速度(进程开销)
3.按需使用
=====
ES6 Module 静态引入,编译时引入;
CommonJS 动态引入,执行时引入;
只有 ES6 Module 才能静态分析,实现 Tree-Shaking
====================
Babel-pollyfill
{ "presets":[ "@babel/preset-env", { "useBuiltIns":"usage", "corejs":3 } ] }
const sum = (a, b) => a + b // 新的 API Promise.resolve(100).then(data => data); // 新的 API [10, 20, 30].includes(20) // 语法,符合 ES5 语法规范 // 不处理模块化(webpack) // 污染全局环境 // window.Promise1 = function() {} // Array.prototype.includes1 = function () {} // 使用方 // window.Promise = 'abc' // Array.prototype.includes = 100
@babel-runtime
一般自己的代码还好,主要是在配置第三方库的时候,建议增加 babel-runtime的配置,避免污染用户的全局变量。
.babelrc 配置:
{ "presets": [ [ "@babel/preset-env", { "useBuiltIns": "usage", "corejs": 3 } ] ], "plugins": [ [ "@babel/plugin-transform-runtime", { "absoluteRuntime": false, "corejs": 3, "helpers": true, "regenerator": true, "useESModules": false } ] ] }
经过babel-runtime编译后,全局变量不在是 promise ,而是变成了 _promise