Webpack 三种文件指纹策略 js、css、图片字体资源的指纹设置

文件指纹

是什么?
文件指纹就是打包输出后文件名的后缀

有什么用?
文件指纹通常可以用来做一些版本管理,在发布的时候,有修改的文件就发布上去,没有修改的文件还可以继续用浏览器本地缓存,这样可以加速页面访问

文件指纹类型以及如何生成

文件指纹有三种类型

  • Hash
  • Chunkhash
  • Contenthash

Hash

和整个项目的构建有关,只要项目文件有修改,整个项目构建的hash就会修改

Compiler 和 Compilation
Compiler: webpack启动的那一次创建的对象
Compilation: 只要有一个文件发生了变化,Compilation就会发生改变。 hash受到Compilation的影响而改变

ChunkHash

ChunkHash和webpack打包的chunk有关,不同的entry入口会生成不同的chunkhash值,使得chunk保持独立

如果a页面变化,那么b页面也会变化,这其实是没必要的,因此需要chunkhash
chunkhash只能用于生产环境,在热更新的时候不会生成

Contenthash

根据文件内容定义hash指纹,文件内容不变,则contentHash不变

如果修改了js,css没有变,如果css也采用chunkhash,导致css内容没有变化但是上传的css chunkhash发生了变化
因此对于css内容,一般都是根据文件内容来生成css指纹

配置指纹

将webpack.config.js拆分为两份
webpack.dev.config
webpack.prod.config

对于生产环境的配置应该去掉热更新相关插件,同时将mode改为production
同时将package.json中的build脚本指定为webpack.prod.config

"build":"webpack --config webpack.prod.js"
"dev":"webpack-dev-server --config webpack.dev.js --open"

设置js文件指纹

直接在output下修改chunkhash
仅当entry入口文件内容有变化时,打包生成的chunkhash值才会变化

配置之前输出:
app.js
react-comp.js

配置之后输出:
app_76762735.js
reactComp_456cec63.js

module.exports = {
    output:{
        path:path.join(__dirname,'./dist'),
        filename:'[name]_[chunkhash:8].js'
    }
}

完整版

'use strict';
const path = require('path');
module.exports = {
    // 生产模式还是开发模式
    mode: 'production',
    // 入口 指定入口文件
    entry: {
        app:'./src/index.js', 
        // search:'./src/search.js',
        reactComp: './src/react-comp.js'
    },
    // 出口 
    output: {
        // 指定输出目录
        path: path.join(__dirname, 'dist'),
        filename: '[name]_[chunkhash:8].js'
    },
    // 配置loader
    module: {
        rules: [
            {
                test: /.js$/,
                use: 'babel-loader'
            },
            {
                test:/.css$/,
                use:[
                    'style-loader', // 再将样式插入到style标签中
                    'css-loader' // 将css转换成commonjs
                ]
            },
            {
                test: /.less$/,
                use: [
                    'style-loader', // 再将样式插入到style标签中
                    'css-loader', // 将css转换成commonjs
                    'less-loader' // 将less文件转换成css文件
                ]
            },
            {
                test: /.(png|jpg|gif|jpeg)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 40 * 1024 // 40k
                        }
                    }
                ]
            },
            {
                test: /.(woff|woff2|eot|ttf|otf|otf)$/,
                use: [
                    'file-loader'
                ]
            }
        ]
    }
}

设置图片字体等文件指纹

设置file-loader或url-loader的name,使用[hash]
此处的hash和前面提到的js hash不一样,这里指的也是文件内容的hash,默认采用md5生成

如果转换成base64则无法查看hash效果,因此先将url-loader改成file-loader,然后给图片设置文件指纹

module.exports = {
    module:{
    rules:[
        {
            test:/.(png|svg|jpg|gif)$/,
            use:[
                loader:'file-loader',
                options:{
                    name:'/img/[name]-[hash:8].[ext]' 
                }
            ]
        }
    ]
}
}

占位符名称
[ext] 资源后缀名
[name] 名称
[path] 相对路径
[folder] 文件所在的文件夹
[contenthash] 文件内容hash,默认由md5生成
[hash] 文件内容hash,默认由md5生成
[emoji] 一个随机指代文件内容的emoji

完整版配置

'use strict';

const path = require('path');

module.exports = {
    // 生产模式还是开发模式
    mode: 'production',
    // 入口 指定入口文件
    entry: {
        app: './src/index.js',
        reactComp: './src/react-comp.js'
    },
    // 出口 
    output: {
        // 指定输出目录
        path: path.join(__dirname, 'dist'),
        filename: '[name]_[chunkhash:8].js'
    },
    // 配置loader
    module: {
        rules: [
            {
                test: /.js$/,
                use: 'babel-loader'
            },
            {
                test: /.css$/,
                use: [
                    'style-loader', // 再将样式插入到style标签中
                    'css-loader' // 将css转换成commonjs
                ]
            },
            {
                test: /.less$/,
                use: [
                    'style-loader', // 再将样式插入到style标签中
                    'css-loader', // 将css转换成commonjs
                    'less-loader' // 将less文件转换成css文件
                ]
            },
            {
                test: /.(png|jpg|gif|jpeg)$/,
                use: [
                    {
                        loader:'file-loader',
                        // 图片指纹
                        options:{
                            name:'[name]_[hash:8].[ext]'
                        }
                    }
                ]
            },
            {
                test: /.(woff|woff2|eot|ttf|otf|otf)$/,
                use: [
                    {
                        loader:'file-loader',
                        options:{
                            name:'[name]_[hash:8].[ext]'
                        }
                    }
                ]
            }
        ]
    }
}

设置css文件指纹

避免css没变js变化的时候,css的chunkhash值也随着打包一起变化,因此css应该使用contenthash,

目前css是以style标签存在于页面中,因此需要使用MiniCssExtractPlugin来抽取成文件再设置文件指纹
因此这个插件和style-loader是互斥的

npm i mini-css-Extract-plugin@0.6.0 -D

配置webpack
除了配置插件外,还需要把插件的loader加进去, 并且这个插件和style-loader是互斥的,因此需要将style-loader替换成MiniCssExtractPlugin.loader

module.exports = {
    loader:{
        rules:[
            {
                test:/.css$/,
                use:[
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                ]
            },
            {
                test:/.less$/,
                use:[
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'less-loader'
                ]
            }
        ]
    }
    plugins:[
        new MiniCssExtractPlugin({
            filename:'[name]_[contenthash:8].css'
        })
    ]
}
原文地址:https://www.cnblogs.com/ltfxy/p/15328214.html