Webpack学习笔记(三) webpack进阶


文件指纹 hash & chunkHash & contentHash

文件指纹用于表示该文件是否变化,常见的文件指纹由hash,chunkHash,contentHash

hash和整个项目的内容相关,如果整个项目内容有变化则hash会发生改变。

测试一下hash,下面的配置用于输出8位hash

output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name]-[hash:8].js'
},

修改文件后再次build,对比一下两次输出可以知道文件hash发生了变化

main-cce3a23b.js
main-6bc662fd.js

chunkHash是指该chunk(webpack打包后的文件)文件内容发生变化后hash会改变,如果是多入口打包项目比较适合chunkHash

output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name]-[chunkhash:8].js'
},

contentHash是指该文件内容发生变化则hash改变,非常适合css这样的文件。如果不对css进行extract,css和js两个文件的内容都在一个bundle内,任意一方内容改变后hash都会改变,因此contentHash配合extractPlugin非常适合css文件

plugins:[
    new MiniCssExtractPlugin({
        filename: '[name][contenthash:8].css'
    })
],

代码压缩

通过压缩代码可以在减轻服务器压力的同时提高用户体验

压缩CSS

压缩css需要使用MiniCssExtractPlugin & cssMinimizerWebpackPlugin

配置loader

{
    test: /.css$/,
    use: [MiniCssExtractPlugin.loader,'css-loader']
}

配置optimization

optimization: {
    minimizer: [
        new CssMinimizerPlugin()
    ]
}

对比一下压缩前后的变化

.content{height:100px;width:100px}

.content{
    width: 100px;
    height: 100px;
}

压缩HTML

使用HtmlWebpackPlugin压缩html

看下配置,该配置默认使用scr下index.html,chunks指定需要注入那些chunk(js,css)

new HtmlWebpackPlugin({
    filename: 'index.html',
    template: 'src/index.html',
    chunks: 'index'
})

对比一下压缩前后代码

<!doctype html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Document</title><script defer="defer" src="main-0bff38bb.js"></script><link href="main285ec44b.css" rel="stylesheet"></head><body><div id="root"></div></body></html>


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="root">

    </div>
</body>
</html>

CSS前缀自动补全

如果项目要在比较老的浏览器上运行,部分属性需要添加前缀(比如transform),可以post css实现自动添加前缀

添加loader, 假设我们要兼容浏览器最近的50个版本

{
    loader: 'postcss-loader',            
    options: {
        postcssOptions: {
            plugins: [
                [
                    "postcss-preset-env",
                    {
                        browsers:["last 50 versions"]
                    }
                ],
            ],
        },
    },
}

看一下build后的文件, 自动添加了相关前缀。

.content{
    -webkit-transform: rotate(30deg);
        -ms-transform: rotate(30deg);
            transform: rotate(30deg);
}

px转vw

为了更方便的进行移动端适配,可以将px转到vw,一种可行的转换方案是依靠postcss+postcss-px-to-viewport

给postcss.config.js添加配置

module.exports = {
    plugins: [
      require('postcss-px-to-viewport')
    ]
}

对比以下转换前后

.content{
    width: 100px;
    height: 100px;
}

.content{
    width: 31.25vw;
    height: 31.25vw;
}

动态import

实现动态import需要借助于@babel/plugin-syntax-dynamic-import,该插件在新的preset-env中已经默认引入

假设我们有一个Content组件,动态import可以这么写(React提供了更好用的React.lazy)

loadComponent(){
    import('./index2.jsx').then((c) => this.setState({component: c.default}))
}

这样webpack在打包之后会分离出一个单独文件

·动态import更加常用的用法是卸载router中,当切换tab时加载新的页面,从而减小首次加载的体积。

公共资源提取

webpack已经实现了一套默认的splitChunks,简单看一下配置

如果不确定自己能做得更好的话推荐使用default config:

The default configuration was chosen to fit web performance best practices, but the optimal strategy for your project might differ. If you’re changing the configuration, you should measure the effect of your changes to ensure there’s a real benefit.

optimization: {
    splitChunks: {
        chunks: 'async',
        minSize: 20000,
        minRemainingSize: 0,
        minChunks: 1,
        maxAsyncRequests: 30,
        maxInitialRequests: 30,
        enforceSizeThreshold: 50000,
        cacheGroups: {
            defaultVendors: {
                test: /([\\/]node_modules[\\/])/,
                priority: -10,
                reuseExistingChunk: true,
            },
            default: {
                minChunks: 2,
                priority: -20,
                reuseExistingChunk: true,
            },
        },
    },
},

解释一下比较重要的几个字段

  • chukns 抽离什么类型的文件,async代表只关注动态引入的文件
  • minSize 公共包超过20000字节时抽离
  • minChunks 该包引用超过一次时考虑抽离

构建日志

webpack config提供了多种构建日志的可选项

在config中添加stats指定构建日志级别

stats: 'errors-only'

下面是常用的stats
stats

可以使用plugin获取更友好的log,比如@soda/friendly-errors-webpack-plugin,安装后在plugin加入配置

plugins: [
    new ErrorPlugin() 
],

接下来构建后会有更友好的提示信息。


Author: Maple
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Maple !
  TOC