webpack4 的生产环境优化

webpack4 的生产环境优化

webpack4完整配置的能够参考: https://github.com/ziwei3749/...css

本文主要介绍了 webpack4 生产环境我都作了哪些优化html

文章的结构以下:前端

  • 1.静态资源路径。
  • 2.hash 缓存。
  • 3.代码分割。
  • 4.压缩混淆代码。
  • 5.开启 gzip 压缩。
  • 6.关闭 devtool。
  • 7.Tree Shaking

1.静态资源路径。对静态资源路径的处理和验证

静态资源包括: js css image,node

静态资源的路径的组成: 前缀 + 本身设置的路径webpack

前缀 :静态资源的路径配置的前缀经过 output.publicPath 设置git

关于publicPath的解释 https://juejin.im/post/5ae9ae...github

本身设置的路径web

js 的路径配置

js 的路径配置在 output.filenameexpress

output: {
    path: path.resolve(__dirname, '../dist'),
    filename: 'static/js/[name].[contenthash:8].js'
}
css 路径配置

css 的路径配置在分离 css 的插件里。例如以前的 extract-text-webpack-plugin 或者 mini-css-extract-pluginnpm

plugins: [
    new MiniCssExtractPlugin({
        filename: "static/css/[name].[contenthash:8].css"
    })
];
image 路径配置

img 的路径配置在 url-loader 里配置

modules: {
    rules: [
        {
            test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
            use: [
                {
                    loader: "url-loader",
                    options: {
                        limit: 10000,
                        name: "static/images/[name].[hash:7].[ext]"
                    }
                }
            ]
        }
    ];
}

ps: 有的前端同窗,可能像我同样不太清楚如何验证打包压缩后的的文件内路径配置的是否正确

推荐一个简单的方法。下载 express 项目脚手架生成一个 node 项目,将打包后的 dist 扔到 public,启动 node 服务器

npm install express-generator -D

固然也能够直接去打开 dist 文件夹里的路径,去确实路径是否正确。

2.hash 缓存。

将业务代码、第三方类库、runtime 代码、css 单独打包,给他们不一样 hash,来最大化利用缓存

webpack3 中分离业务代码、第三方类库须要用 CommonChunksPlugin。
webpack4 的新增 optimization,能够方便的分离代码,并且 hash 的稳定性的问题也有改进。

单独打包业务代码、第三方类库、runtime

optimization: {
        splitChunks: {      // 打包 node_modules里的代码
            chunks: 'all'
        },
        runtimeChunk: true,  // 打包 runtime 代码
    }

单独打包 css 代码

webpack4 推荐 mini-css-extract-plugin

注意: 以前的 extract-text-webpack-plugin 须要 beta 版本才支持,并且 contenthash 没法使用。

分配不一样的 hash

关于 hash 稳定性的坑

注意区分

  • [hash] : 整个项目有变更时,hash 变化。
  • [chunkhash] : chunk 有变更,chunkhash 变化
  • [contenthash] : 目前文档没有明肯定义和说明,可是和文件内容的变化相关

在分离 js 和 css 时,都用设置 contenthash.

output: {
    path: path.resolve(__dirname, '../dist'),
    filename: 'static/js/[name].[contenthash:8].js',
    publicPath: '/'
  },
new MiniCssExtractPlugin({
      filename: 'static/css/[name].[contenthash:8].css'
    }),
配置js的文件名时,以前webpack3都是用chunkhash也没问题,可是实践后发现webpack4中用chunkhash,会致使,修改css时引起js的chunkhash变化,从而缓存失效。

经测试这样的设置,的确能够分离打包,而且各自的 hash 值互相不会干扰,若是有问题的话,能够共同讨论

3.代码分割

代码分割或者说懒加载,是 webpack 从诞生就一直标榜的功能吧。

它的做用就是把 js 分割成几份,在用户须要加载时才加载,这样不用一次性加载全部 js。

那么在 webpack 里实现代码分割并非用配置的方式,而是经过咱们写代码的方式来告诉 webpack 哪些代码要分割

webpack 里有 2 种 webpack 分割方法

  • webpack 内置方法 : require.ensure() 和 require.include()
  • es2015 定义的 动态 import,import 返回 promise

require.ensure 使用 demo

// require.ensure()的 4 个参数 : []依赖 、 callback 、 errorCallback 、 chunkName
require.ensure(
    ["./subPageA"],
    () => {
        var subPageA = require("./subPageA");
    },
    "subPageA"
);

// require.include('./moduleA.js')能够提取异步模块中的公共部分到父chunk

import 使用 demo

import("./subPageA").then(subPageA => {
    console.log(subPageA);
});

// 区别
//  import('./subPageA')会直接执行这个文件,
//  而require.ensure()不会直接执行,是在里面的回调函数里才执行的引入操做。
关于import的使用注意
@babel升级后,使用import的语法,须要下载插件 @babel/plugin-syntax-dynamic-import

如下的地址连接
https://babeljs.io/docs/en/next/babel-plugin-syntax-dynamic-import.html

4.压缩混淆代码

据说webpack4只须要设置mode:produciton,就自动打包混淆js代码啦!

很好,如今咱们只须要压缩css了能够了呢,因而下载插件optimize-css-assets-webpack-plugin

const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
optimization: {
    splitChunks: {
      chunks: 'all'
    },
    runtimeChunk: true,
    minimizer: [
      new OptimizeCssAssetsPlugin({})
    ]
  },
new OptimizeCssAssetsPlugin({
      assetNameRegExp: /\.optimize\.css$/g,
      cssProcessor: require('cssnano'),
      cssProcessorOptions: { safe: true, discardComments: { removeAll: true } },
      canPrint: true
    }),

再看一眼咱们的代码,坑爹的发现js的压缩竟然失效了。

为何呢?我在问答社区看到相似的问题,而且在官方文档找到了解释。

大体意思就是。默认optimization.minimize是true,因此js能够自动帮你压缩

可是自定义minimizer后,webpack默认配置会取消掉。

文档还很皮的告诉你,若是你用了css压缩,记得本身用uglifyjs压缩js呀。。。

总之,仍是要本身用uglifyjs配置后压缩js

minimizer: [
      new OptimizeCssAssetsPlugin({}), // 压缩 css,使用minimizer会自动取消webpack的默认配置,因此记得用UglifyJsPlugin
      new UglifyJsPlugin({
        // 压缩 js
        uglifyOptions: {
          ecma: 6,
          cache: true,
          parallel: true
        }
      })
    ]

5.开启 gzip 压缩。

开启gzip压缩,那么压缩的好处是什么?

能够减少文件体积,传输速度更快。

  • 服务端发送 response 时能够配置 Content-Encoding:gzip,用户说明数据的压缩方式
  • 浏览器接受时,就能够根据相应个格式去解码。客户端请求时,能够用 Accept-Encoding:gzip,用户说明接受哪些压缩方法

因此 gzip 格式在 http 中传输文件的话,速度更快。那么谁来压缩文件?

不是服务端,就是客户端咯。

  • 服务端好比 ngix 或者 node 去作压缩,
  • 也能够 webpack 打包上线时,经过插件去作压缩。

服务端响应时压缩,确定不如应用构建时压缩更合适。由于压缩也是要有时间开销的

const CompressionWebpackPlugin = require('compression-webpack-plugin');

webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp('\\.(js|css)$'),
      threshold: 10240,
      minRatio: 0.8
    })
)

压缩以后,文件体积减小的确显著。

6.关闭devtool

devtool我没有作很深刻的研究。

个人理解,开发环境必需要配置,不然确定没法调试。

而生产环境能够这一项,由于咱们不须要在生产环境调试代码。若是理解有误,欢迎指正哈~

7.Tree shaking

tree shaking 的原理

  • ES6 的模块是静态分析的。因此在编译时能够判断哪些代码没有 exports
  • 分析程序流,判断哪些变量没有被使用、从而删除代码

webpack4的新增了sideEffects来指定“有反作用的文件”,

可是我在实际使用时,遇到一些坑,好比这样配置后,我意思是指定.css文件不要被“摇”掉。

但这个配置依旧致使了css文件打包后被当作冗余代码被删除。

"sideEffects": [
    "*.css"
  ],

关于tree shaking就贴一篇文章。关于tree shaking研究清楚后再更新吧

https://zhuanlan.zhihu.com/p/...

以上就是整个配置的说明啦,目前tree shaking目前尚未搞定,其余功能我本身测试是没有问题的。

贴一份,webpack4完整的配置文件的地址。

若是以为有帮助但愿star一下,若是遇到问题,也欢迎指教!

相关文章
相关标签/搜索