webpack补充点---查漏补缺

 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中的一个属性,作用:
不去解析属性值代表的库的依赖

我们一般引用jquery,可以如下引用:
import jq from 'jquery'
对于上面的解析规则:
当解析jq的时候,会去解析jq这个库是否有依赖其他的包

我们对类似jq这类依赖库,一般会认为不会引用其他的包(特殊除外,自行判断)。所以,对于这类不引用其他的包的库,我们在打包的时候就没有必要去解析,这样能够增加打包速率。
所以,可以在webpack的配置中增加noParse属性(以下代码只需要看module的noParse属性)
 
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

polyfill是为了兼容新语法的代码
core-js 和 regenerator 是官方提供的 polyfill
babel-polyfill 是core-js 和 regenerator 的集合,支持所有新语法的兼容代码
babel 7.4 之后推荐直接使用 core-js 和 regenerator

poly-fill的按需加载
.babelrc文件

{
  "presets":[
    "@babel/preset-env",
    {
      "useBuiltIns":"usage",
      "corejs":3
    }
  ]
}

然后删除掉js中引入的 pollyfill

import '@babel/polyfill' //删除掉

所以 @babel/polyfill 已经被弃用, 只需要安装corejs即可。
 
但是这样引入会带来全局变量污染的问题,比如
 
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

原文地址:https://www.cnblogs.com/xiaozhumaopao/p/12730586.html