webpack 为chunk加随机数_chunk webpack - CSDN
精华内容
参与话题
  • webpack配置整理

    2018-05-11 15:25:22
    自从node出现带来的前端大爆炸时代以来,前端工程化构建相关的工具层出不穷,如fis、gulp、grunt、webpack等,但如果让我说最全面的构建工具,那非webpack...因为眼下webpack4.*出现,所以此次整理以4.*主,在整理...

    自从node出现带来的前端大爆炸时代以来,前端工程化构建相关的工具层出不穷,如fis、gulp、grunt、webpack等,但如果让我说最全面的构建工具,那非webpack莫属了。

    “webpack一统天下!”

    最近看掘金小册中有一篇关于webpack的配置,从头撸了一遍感觉收获颇丰,所以实践、整理、记录一下整个过程相关学习。因为眼下webpack4.*出现,所以此次整理以4.*为主,在整理过程中会尽可能理清3.*4.*的区别,以求更清晰的分析和理解。

    ※※※: 新建文件

    $$$ : 新依赖

    安装和环境区分

    一般来说我们更多的将webpack作为项目开发依赖来安装使用,并且固定版本,有利于多人协作开发。

    项目init,保证项目有package.json文件 。※※※

    npm init

    安装webpackwebpack-cli,并作为项目开发依赖(此处默认使用webpack4.8.1版本)$$$

    npm install webpack webpack-cli -D

    接下来,我们需要在package.json中添加相关script。

    1. 此处的—mode参数,是webpack4.*不可缺少的参数,用于区分当前环境,关于环境区分后续会讲。
    2. webpack-dev-server模块需要安装,在本地开启一个简单的静态服务来进行开发。$$$
    npm install webpack-dev-server -D 
    "scripts": {
        "build": "webpack --mode production",
        "start": "webpack-dev-server --mode development"
    },

    由于webpack 4.x 的版本可以零配置就开始进行构建,但是为了更定制化,我们还需要自己配置自己的config文件。接下来我们来新建和配置自己的webpack.config.js文件。※※※

    webpack的构建离不开一个入口文件,webpack会读取这个文件,从他开始解析依赖,打包等操作。所以我们需要新建一个入口文件entry.js文件。※※※

    webpack配置最终export一个对象或者一个函数,此处我们使用函数形式。

    module.exports= {}
    
    // 或者 webpack 4.0 暴露一个函数,可以获取到mode的环境变量
    module.export = (env, argv) => {
        console.log(env, argv.mode)
        return {
            entry: {
                index: './entry.js'
            }
        }
    }

    此时我们可以试着启动项目,来查看打印出来的mode是否是对应的development和production。

    npm start   // => undefined development
    npm run build   // => undefined production

    区分环境除了用webpack4.*—mode参数,还可以用如下script,还可以将两者集合:

    "scripts": {
        "build_": "NODE_ENV=production webpack",
        "start_": "NODE_ENV=development webpack-dev-server"
    },

    webpack.config.js中可以打印process.env.NODE_ENV查看

    // webpack.config.js
    console.log('process.env.NODE_ENV =====>', process.env.NODE_ENV)
    
    npm run start_  // => development
    npm run build_  // => production

    环境区分之后,我们就可以实现dev和prd不同的配置,以达到我们想要的效果。

    常用配置

    我们回到webpack的配置中来,webpack配置常用的主要字段为:

    • entry 入口
    • output 出口
    • resolve 处理依赖模块路径的解析
    • module 处理多种文件格式的loader
    • plugins 除了文件格式转化由loader来处理,其他大多数由plugin来处理
    • devServer 配置 webpack-dev-server
    • optimization 优化,如4.*的chunk分离等

    entry

    如下代码中, indexvendor 是多入口名称,后续打包过程会有用!项目可以单入口也可以多入口。

    vendor指向node_module中的vue组件,是为了后续chunk分离出单独的js文件,因为不常修改,可以单独打包而且可以使用chunkhash来维持相同的hash值,保证用户最大程度利用浏览器缓存机制。

    {
        entry: {
            vendor: ["vue"],
            index: './src/index.js'
        }
    }

    output

    如下代码中,[name]是根据entry中的多入口的名字。此处还可以获取[hash]、[chunkhash]等,用于相应的需求。代码中?rd=[hash] 是为了配合接下来的html-webpack-plugin,可以将js插入html中并加上随机数,实现清缓存功能。

    [chunkhash]可以保证当chunk的部分不变化情况下,不变化hash值,实现最大程度利用缓存机制。

    注意:后续热更新(HMR)不能和[chunkhash]同时使用。 解决:如果是开发环境,将配置文件中的chunkhash 替换为hash

    {
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: '[name].js?rd=[hash:8]'
        }
    }

    resolve

    webpack 中有一个很关键的内部模块 enhanced-resolve 就是处理依赖模块路径的解析的。

    modules:指定了全局的node_modules,为了避免在内部一层层查找node_module文件夹,优化性能:

    extensions:指定了一个可以省略后缀名的文件类型数组,一般不推荐使用太多,有查找性能问题。

    alias:指定了访问路径的别名,可以在项目中直接访问如:import "css/a.less"

    resolve: {
        modules: [
            // 使用绝对路径指定项目 node_modules,不做过多(一层层)查询
            path.resolve(__dirname, 'node_modules'), 
        ],
        extensions: ['.vue', '.js', '.json', '.jsx', '.css'],
        alias: {
            'css': path.resolve(__dirname, 'src/assets/css')
        }
    },

    module

    webpack 中提供一种处理多种文件格式的机制,便是使用 loader。我们可以把 loader 理解为是一个转换器,负责把某种文件格式的内容转换成 webpack 可以支持打包的模块。

    这里举例常用的几个loader,更多的loader可以查看:webpack loader

    rules是一个数组,包括多个loader

    test: 匹配文件路径的正则表达式,通常我们都是匹配文件类型后缀

    include: 指定哪些路径下的文件需要经过 loader 处理,node_module不需要处理,性能问题

    loader: 单个loader可以直接用这个字段,否者可以用use字段,这些loader一般都需要安装依赖 $$$

    use:指定使用的loader,use字段是一个数组,注意顺序问题,先使用的loader需要排在后面,ExtractTextPlugin是模块extract-text-webpack-plugin用于将文件分离,这个plugin比较特殊需要loader的配合,后续讲解。

    // 简单的loader
    module: {
        rules: [{
            test: /\.(less|css)$/,
            include: [
                path.resolve(__dirname, 'src')
            ],
            use: [
                { loader: 'css-loader'},
                { loader: 'style-loader'}
            ]
        }]
    }
    
    // 如果结合ExtractTextPlugin插件分离文件和postcss-loader等其他loader
    module: {
        rules: [{
            test: /\.(less|css)$/,
            include: [
                path.resolve(__dirname, 'src')
            ],
            use: ExtractTextPlugin.extract({
                use: [{
                    // 负责解析 CSS 代码,主要是为了处理 CSS 中的依赖,
                    // 例如 @import 和 url() 等引用外部文件的声明
                    loader: 'css-loader',
                    options: {
                        minimize: true, // 使用 css 的压缩功能
                    },
                },
                      { loader: 'postcss-loader'},
                      { loader: 'less-loader' }
                     ],
                // 会将 css-loader 解析的结果转变成 JS 代码,
                // 运行时【动态】插入 style 标签来让 CSS 代码生效
                fallback: 'style-loader'
            })
        }]
    }

    常用的loader还有:

    url-loader,url-loader 和 file-loader 的功能类似,但前者可以转成base64 $$$

    image-webpack-loader,image-webpack-loader 的压缩是使用 imagemin 提供的一系列图片压缩类库来处理的 $$$

    babel-loader,这个不多说了,es6离不开babel。 $$$

    plugins

    模块代码转换的工作由 loader 来处理,除此之外的其他任何工作都可以交由 plugin 来完成,plugin分为webpack内置和第三方的。

    CopyWebpackPluginHtmlWebpackPluginExtractTextPlugin都是非常重要的plugin。具体看代码中的注释:$$$

    const UglifyPlugin = require('uglifyjs-webpack-plugin')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    const ExtractTextPlugin = require('extract-text-webpack-plugin')
    const CopyWebpackPlugin = require('copy-webpack-plugin')
    
    plugins: [
            new webpack.DefinePlugin({
                'process.env': {
                    NODE_ENV: JSON.stringify(process.env.NODE_ENV) 
                }
            }),
            // 直接将static文件复制到dist中
            new CopyWebpackPlugin([
                { from: 'static/*.*', to: '', } 
            ]),
            // webpack 4.x 版本运行时,mode 为 production 即会启动压缩 JS 代码的插件,
            // 屏蔽此插件,3.x可以用这个插件
            new UglifyPlugin(),
            // 如果我们的文件名或者路径会变化,例如使用 [hash] 来进行命名,那么最好是将 HTML 引用路径和我们的构建结果关联起来,这个时候我们可以使用 html-webpack-plugin。
            // 如果需要添加多个页面关联,那么实例化多个 html-webpack-plugin, 并将它们都放到 plugins 字段数组中就可以了。
            new HtmlWebpackPlugin({
                filename: 'index.html', // 配置输出文件名和路径
                template: './index.html',    // 配置html文件模板,将js和这个关联起来
                minify: { // 压缩 HTML 的配置
                    minifyCSS: true, // 压缩 HTML 中出现的 CSS 代码
                    minifyJS: true, // 压缩 HTML 中出现的 JS 代码
                    removeComments: true,   // 移除注释
                    collapseWhitespace: true,   // 缩去空格
                    removeAttributeQuotes: true // 移除属性引号
                }
            }),
            // 使用方式特别,除了在plugins字段添加插件实例之外,还需要调整 loader 对应的配置。
            // 配置输出的文件名,这里同样可以使用 [hash],多个文件会加载在一起
            // name 是根据entry中的入口名字
            new ExtractTextPlugin({
                filename: '[name].css?rd=[hash:8]'
            }),
            // 在 HMR 更新的浏览器控制台中打印更易读的模块名称
            new webpack.NamedModulesPlugin(),   
            // Hot Module Replacement 的插件
            //【在这个概念出来之前,我们使用过 Hot Reloading,当代码变更时通知浏览器刷新页面】
            //【HMR 可以理解为增强版的 Hot Reloading,不用整个页面刷新,而局部替换掉模块】
            new webpack.HotModuleReplacementPlugin()
        ],

    devServer

    在 webpack 的配置中,可以通过 devServer 字段来配置 webpack-dev-server,如端口设置、启动 gzip 压缩等,这里简单讲解几个常用的配置。

    一般来说只要使用hot: true ,来实现模块热替换。

    devServer: {
        // public: 'http://localhost:8080/',   // public 字段用于指定静态服务的域名
        // publicPath: 'static/',      // 字段用于指定构建好的静态文件在浏览器中用什么路径去访问
        port: '1234',
        hot: true,  // 模块热替换
        before(app) {
            // 当访问 /some/path 路径时,返回自定义的 json 数据
            // 可以用于拦截部分请求返回特定内容,或者实现简单的数据 mock。
            app.get('/api/test.json', function (req, res) { 
                res.json({ code: 200, message: 'hello world' })
            })
        },
        /* proxy: {
            '/login': {
                target: 'http://127.0.0.1:8090',
                changeOrigin: true,
                pathRewrite: {
                    '^/login': '/login'
                }
            }
        } */
    },

    optimization

    webpack配置优化,比如webpack4.* chunks分离就移到这里很简单的设置:

    在webpack3.*中,想实现chunks分离需要用到webpack.optimize.CommonsChunkPlugin插件:

    plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',         // 使用 vendor 入口作为公共部分
            filename: "vendor.js",  
            // minChunks: 3,        // 公共的部分必须被 3 个 chunk 共享
            minChunks: Infinity,    // 这个配置会让webpack不再自动抽离公共模块,不管超过多少都不抽离,只抽离指定的vendor
        })   
    ]

    在webpack4.*中,分离chunks移到了optimization中:

    optimization: {
        // webpack4.* chunks分离
        splitChunks: {
            // chunks: "all", // 所有的 chunks 代码公共的部分分离出来成为一个单独的文件
            cacheGroups: {
                vendor: {
                    chunks: "initial",
                    test: "vendor",
                    name: "vendor", // 使用 vendor 入口作为公共部分
                    enforce: true,
                },
            }
        }
    }

    中间件

    熟悉Node的都知道中间件,简单的说是来完成某件事情的插件。比如webpack-dev-middleware就是在 Express 中提供 webpack-dev-server 静态服务能力的一个中间件 【dev】 $$$

    npm install webpack-dev-middleware express -D

    接下来我们创建一个dev.js,然后我们用node dev.js来执行,dev.js代码如下:

    const webpack = require('webpack')
    const chalk = require('chalk')      // 命令行中彩色出书
    const opn = require('opn')          // 自动打开浏览器
    const ora = require('ora')          // loading样式
    const midddleware = require('webpack-dev-middleware')   
    const webpackOptions = require('./webpack.config.js')
    
    const spinner = ora({
        text: chalk.magenta('> 加载中...'),
        spinner: 'bouncingBar'
    }).start()
    const port = 3000
    
    // 本地的开发环境,可以再次全局设置mode,用于webpack配置中获取。如果script中设置了,就不需要这里设置了。
    webpackOptions.mode = 'development'
    const compiler = webpack(webpackOptions)
    
    const express  = require('express')
    const app = express()
    
    let hotMidddleware = midddleware(compiler, {
        // webpack-dev-middleware 的配置选项
    })
    app.use(hotMidddleware)
    
    // 编译完成的回调函数
    hotMidddleware.waitUntilValid(() => {
        spinner.stop()
        console.log(chalk.magenta('> 编译完成...'))
        console.log(chalk.magenta(`> 监听:http://localhost:${port}\n`))
        opn(`http://localhost:${port}`)
    })
    
    app.listen(port, () => {
        console.log(chalk.magenta('> 项目运行...'))
    })

    有了这样的中间件,我们完全可以创建一套cli,区分开发、测试、生产打包的配置。具体可以尝试实践,回头看vue-cli的配置,大体上没什么大问题了。

    总结

    env相关总结:

    webpack 3:

    ​ package.json中 “start_”: “NODE_ENV=development webpack-dev-server”

    1. 在webpack.config.js中可以获取 process.env.NODE_ENV
    2. 在runtime项目代码中【不能】获取到 process.env.NODE_ENV,默认为production。要想在项目中获取,需要webpack.DefinePlugin这个plugin设置

    webpack 4:

    ​ package.json中 “start”: “webpack-dev-server –mode development”

    1. 在webpack.config.js中【不能】获取process.env.NODE_ENV,需要把配置作为函数返回值暴露 module.exports = (env, argv) => {},其中arv.mode可以获取
    2. 在runtime项目代码中可以获取到 process.env.NODE_ENV。(注意不要设置webpack.DefinePlugin)
    3. 更加快速的增量编译构建。(hot reload比 webpack 3比较快)

    我觉得可以集合两者,定义script中为"start": "NODE_ENV=development webpack-dev-server --mode development"

    postcss

    这里只说其中一种方法:

    1. 安装依赖postcss-loader以及其他的postcss的plugin, $$$

      npm install postcss-loader autoprefixer -D
    2. 根目录目录建 .postcssrc.js

      module.exports = {
         "plugins": {
             // to edit target browsers: use "browserlist" field in package.json
             "autoprefixer": {}
         }
      }
    3. package.json中添加browserslist

      "browserslist": [
         "defaults",
         "not ie < 8",
         "last 2 versions",
         "> 1%",
         "iOS 7",
         "last 3 iOS versions"
       ]
    4. webpack.config.js的匹配css的loader中加上postcss-loader

    懒加载

    遵循 ES 标准的动态加载语法 dynamic-import 来编写,如果你使用了 Babel 的话,还需要 Syntax Dynamic Import 这个 Babel 插件来处理 import() 这种语法。

    项目代码中:

    setTimeout(() => {  // 模拟异步
        // 注释指定了chunk名
        import(/* webpackChunkName: "lodash_" */ './lodash.js').then((res) => {
            console.log(res)
        }) 
    }, 5000);

    安装依赖"babel-plugin-syntax-dynamic-import"

    npm install babel-plugin-syntax-dynamic-import -D

    项目根目录创建.babelrc文件

    {   
        "presets": [["env", { "modules": false }]],
        "plugins": [
            "syntax-dynamic-import"
        ]
    }

    webpack.config.js中首先要有laoder,再者output中添加chunkFilename,为了分离出来有对应的名字:

    output: {
        path: path.resolve(__dirname, 'dist'),
        chunkFilename: '[name].js?rd=[hash:5]'
    },
    module: {
            rules: [{
                test: /\.jsx?/, // 支持 js 和 jsx;x可有可无
                include: [
                    // src 目录下的才需要经过 babel-loader 处理
                    path.resolve(__dirname, 'src')
                ],
                loader: 'babel-loader',
            }]
    }
    展开全文
  • 使用webpack实现静态资源缓存

    千次阅读 2018-11-26 14:43:55
    回到本文主题,在使用webpack构建的项目中,稍有不慎的话,即使服务器设置了缓存策略,可能构建的项目无法实现静态资源缓存。那么webpack怎样才能达到使用缓存的效果呢,下面就来谈谈这个问题。 区分一下几种不同的...

     

    引言

    静态资源缓存是前端性能优化的一个点,所以在前端开发过程中,一般会最大限度的利用缓存(这里主要是强缓存)。回到本文主题,在使用webpack构建的项目中,稍有不慎的话,即使服务器设置了缓存策略,可能构建的项目无法实现静态资源缓存。那么webpack怎样才能达到使用缓存的效果呢,下面就来谈谈这个问题。

    区分一下几种不同的hash

    我们都知道,webpack有各种hash值,包括每次项目构建hash,不同入口的chunkhash、文件的内容contenthash,这么多hash,它们有什么区别呢?

    hash

    hash是跟整个webpack构建项目相关的,每次项目构建hash对应的值都是不同的,即使项目文件没有做“任何修改”。

    其实是有修改的,因为每次webpack打包编译都会注入webpack的运行时代码,导致整个项目有变化,所以每次hash值都会变化的。

    以本人项目代码为例,代码两次构建前后没有做任何修改的对比图

    可以看出,前后两次对应项目构建hash改变了。由此推断使用该方式是无法达到缓存的,因为每次hash都会变化。

    chunkhash

    chunkhash,从字面上就能猜出它是跟webpack打包的chunk相关的。具体来说webpack是根据入口entry配置文件来分析其依赖项并由此来构建该entry的chunk,并生成对应的hash值。不同的chunk会有不同的hash值。一般在项目中把公共的依赖库和程序入口文件隔离并进行单独打包构建,用chunkhash来生成hash值,只要依赖公共库不变,那么其对应的chunkhash就不会变,从而达到缓存的目的。

    一般在项目中对webpack的entry使用chunkhash,具体表现在output配置项上:

    moudule.exports = {
      entry: {
       app: './src/main.js',
       vendor: ['react', 'redux', 'react-dom', 'react-redux', 'react-router-redux']
      },
      output: {
        path:path.join(__dirname, '/dist/js'),
        filename: '[name].[chunkhash].js'
      }
     ...
    }

    最后app和vendor的chunkhash编译结果如下图

    contenthash

    contenthash表示由文件内容产生的hash值,内容不同产生的contenthash值也不一样。在项目中,通常做法是把项目中css都抽离出对应的css文件来加以引用。比方在webpack配置这样来用:

    module.exports = {
      ...
      plugins: [
         new ExtractTextPlugin({
        filename: 'static/[name]_[chunkhash:7].css',
        disable: false,
        allChunks: true
         })
      ...
      ]

    上面配置有一个问题,因为使用了chunkhash,它与依赖它的chunk共用chunkhash。

    比方在上面app chunk例子中依赖一个index.css文件,index.css的hash是跟着app的chunkhash走的,只要app文件变更的话,那么即使index.css文件没有变化,它的hash值也是会跟着变化的,导致缓存失效。

    那么这时我们可以使用extra-text-webpack-plugin里的contenthash值,保证即使css文件所处的模块里就算其他文件内容改变,只要css文件内容不变,它的hash值就不会变。

    实现js缓存

    webpack插件CommonsChunkPlugin的主要作用是抽取webpack项目入口chunk的公共部分,具体的用法就不做过多介绍,不太了解可以参考webpack官网介绍;

    该插件是webpack项目常用的一个优化功能,几乎在每个webpack项目中都会用到。使用该插件带来的好处:

    • 提升webpack打包速度和项目体积:将webpack入口的chunk文件中所有公共的代码提取出来,减少代码体积;同时提升webpack打包速度。

    • 利用缓存机制:依赖的公共模块文件一般很少更改或者不会更改,这样独立模块文件提取出可以长期缓存。

    但是在项目中,若插件打开方式不正确的话,上面的第二点其实是无法实现,因为这种情况下:

    没有被修改过的公有代码或库代码打包出的Entry Chunk,会随着其他业务代码的变化而变化,导致页面上的长缓存机制失效。

    那么,下面就来开启CommonsChunkPlugin正确的打开方式。

    CommonsChunkPlugin不正确用法

    假如将我们项目的公共库如react、react-dom、react-router与业务代码隔离,将其提取为vendor chunk,webpack配置如下:

    const webpack = require("webpack");
    const path = require('path');
    module.exports = {
      entry: {
        app: "./src/main.js",
        vendor: ["react","react-dom", "redux", "react-redux", "react-router-redux"]
      },
      output: {
        path: path.resolve(__dirname, 'output'),
        filename: "[name].[chunkhash].js"
      },
      plugins: [
        new webpack.optimize.CommonsChunkPlugin({names: ["vendor"]})
      ]
    };

    上面将项目一些基础库打包成一个名为vendor的chunk中,并将业务相关的代码打包到一个名为app的chunk中;

    webpack打包编译后的结果如下:

    我们对其中的业务代码app.js进行修改后,重新编译结果如下:

    可以发现,在CommonsChunkPlugin这种配置下,当业务代码app发生变化,而库代码也跟着变化,vender的chunkhash也跟着变化,这样vendor的引用的名称跟着变化,导致浏览器端的长缓存机制失效。

    引起问题的原因

    引起webpack每次打包编译时vendor跟着变化的原因:

    webpack每次build的时候都会生成一些运行时代码。当只有一个文件时,运行时代码直接塞到这个文件中。当有多个文件时,运行时代码会被提取到公共文件中,也就是上面CommonsChunkPlugin配置的vendor chunk中。

    webpack每次编译时产生的运行时代码,包括全局webpackJsonp方法的定义和维护模块依赖关系,具体可以参考这里>>

    所以,上面webpack的CommonsChunkPlugin配置中,每次编译时这些代码都会打包到vendor中,导致每次vendor的chunkhash每次都会变化。

    那么,我们可以在对vendor chunk进行配置,抽取其中的公共代码,即webpack运行时代码,这样就可以将项目依赖的基础库模块与业务模块隔离开来,因为不会对这些文件进行修改,所以这些文件可达到长缓存的作用。具体配置如下:

    module.exports = {
      entry: {
        app: "./app.js",
        vendor: ["react","react-dom", "redux", "react-redux", "react-router-redux"]
      },
      ....
      plugins: [
        new webpack.optimize.CommonsChunkPlugin({names: ["vendor"]}),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'manifest',
            chunks: ['vendor']
        })
      ]
    };

    这样,即使修改业务app代码,项目依赖的基础库vendor chunk也不会发生变化;只是抽取的manifest chunk每次还会变化,但是这个文件体积非常小,相比vendor来说这种方式的收益更大。如下图:

    修改app代码后的打包编译结果如下,可以看到vendor的chunkhash没有变化

    在webpack中配置CommonsChunkPlugin时需要注意几点:

    1、 配置webpack的output项时,其filenamechunkFilename必须使用chunkhash。不要使用hash,否则即使按照上面的配置也不能达到预期的效果。至于hash与chunkhash的区别,可参考github的回答

    2、对于图片、字体等静态资源抽离使用的file-loader,其配置的hash表示的是静态文件的内容hash值,不是webpack每次打包编译生成的hash值, 切记!!!

    3、对于抽取的css样式文件,需要使用contenthash, 与file-loader中的hash意义相同。此处不能为chunkhash,否则其与抽取该样式文件的entry chunk的chunkhash保持一致,打不到缓存的目的。

    实现css的缓存

    webpack实现css的缓存,就是使用上面介绍过的contenthash,该hash属性值其实是extra-text-webpack-plugin计算的。具体实现css的缓存,其实就像下面一样使用contenthash即可

    module.exports = {
      ...
      plugins: [
         new ExtractTextPlugin({
        filename: 'static/[name]_[contenthash:7].css',
        disable: false,
        allChunks: true
         })
      ...
      ]

    实现图片/字体的缓存

    对于图片、字体等静态资源,在使用webpack构建提取时,其实是使用了file-loader来完成的,生成对应的文件hash值也就是由对应的file-loader来计算的。那么这些静态文件的hash值使用的是什么hash值呢,其实就是hash属性值。如下面代码所示:

    module.exports = {
     ...
     rules: [
       ...
        {
          test: /\.(gif|png|jpe?g)(\?\S*)?$/,
          loader: require.resolve('url-loader'),
          options: {
            limit: 10000,
            name: path.posix.join('static',  '[name]_[hash:7].[ext]')
          }
        },
        font: {
          test: /\.otf|ttf|woff2?|eot(\?\S*)?$/,
          loader: require.resolve('url-loader'),
          options: {
            limit: 10000,
            name: path.posix.join('static', '[name]_[hash:7].[ext]')
          }
        }
     ]
    }

    可以看到上面使用的是hash属性值,此hash非webpack每次项目构建的hash,它是由file-loader根据文件内容计算出来的,不要误认为是webpack构建的hash。

    参考

    1、webpack之CommonsChunkPlugin正确打开方式
    2、webpack 填坑之路--提取独立文件(模块)
    3、webpack代码分割技巧
    4、听说你用webpack处理文件名的hash?那么建议你看看你生成的hash对不对
    5、chunkhash
    6、multiple-commons-chunks
    7、用 webpack 实现持久化缓存
    8、Webpack中hash与chunkhash的区别,以及js与css的hash指纹解耦方案

    展开全文
  • webpack生态中存在多种计算hash的方式: hash chunkhash contenthash hash 代表每次webpck编译中生成的hash值,所有使用这种方式的文件hash都相同。每次构建都会使用webpack计算新的hash。 chunkhash 基于入口文件...

    webpack生态中存在多种计算hash的方式:

    • hash
    • chunkhash
    • contenthash

    hash

    代表每次webpck编译中生成的hash值,所有使用这种方式的文件hash都相同。每次构建都会使用webpack计算新的hash。

    chunkhash

    基于入口文件entry及其关联的chunk生成,某个文件的改动只会影响与它有关联的chunk的hash值,不会影响其他文件

    conenthash

    根据文件内容创建,当文件内容发生变化时,contenthash发生变化。

    避免相同随机值

    webpack在计算hash后分割chunk。产生相同随机值可能是因为这些文件属于同一个chunk,可以将某一个文件提到独立的chunk,放入entry

    展开全文
  • 在我们使用 “npm run build” 打包Vue时,会发现文件的js和css等文件前,都会有一段随机码(hash码),给部署时带来一定的困扰 前端打包出来的效果: ...找到项目中的build/webpack.prod.conf.js 在图示位置中,

    在我们使用 “npm run build” 打包Vue时,会发现文件的js和css等文件前,都会有一段随机码(hash码),给部署时带来一定的困扰

    前端打包出来的效果:

    打包放到后端,放多几次后,会发现有好几个文件:

    虽然在index.html中,会自动生成好是加载哪些文件,但终究还是有的繁琐。

    原因就是打包时Vue会给文件加上一段哈希码,用来校验文件的,可是实际使用时我们又不会怎么用到。

    解决方法:

    找到项目中的build/webpack.prod.conf.js

    在图示位置中,将箭头所指位置修改即可

        // 生成js文件时不要hash码
        filename: utils.assetsPath('js/[name].js'),
        // filename: utils.assetsPath('js/[name].[chunkhash].js'),
    
    
          // 生成css文件时不要hash码
          filename: utils.assetsPath('css/[name].css'),
          // filename: utils.assetsPath('css/[name].[contenthash].css'),

    至于其中的 chunkFilename 要不要改呢?我个人建议是不改

    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')

    因为chunkFilename是何方神圣,我查阅了资料,没有找到官方的具体说明,大概就是在生成一些临时文件时,才会生成这种chunkFile,那么这些我们平时用不上,所以还是建议原生态比较好。

    再次打包,文件名看起来就清爽多了。

    参考链接:

    https://blog.csdn.net/sd19871122/article/details/103630225

    https://www.cnblogs.com/toward-the-sun/p/6147324.html

    展开全文
  • 浏览器缓存问题

    2018-07-18 17:41:05
    不论面试还是工作中,经常遇到浏览器缓存的问题,例如,样式图片等改好了,也提交了,用户那边还是未解决,你可以在webpack里面配置一下,hash值,每次输出的文件名不一样,浏览器就会重新加载。 找到你的webpack...
  • 默认,打包的时候,js和css文件名会带上一串随机数,每次打包,随机数都不同,导致上线部署的时候,需要先删除旧的文件,再解压,操作繁琐。 如果不删除旧的文件,直接解压,服务器的文件夹占用的磁盘空间会越来越大...
  • filenameHashing Type: boolean Default: true 用途 设置打包生成的的静态资源的文件名中是否加入hash以便控制浏览器缓存问题。 用法 ...module.exports = { publicPath: './', // 基本路径 outputDir: 'dist', //...
  • 在vue.config.js文件中... // webpack配置 chainWebpack: config => { if (process.env.NODE_ENV === 'production') { // 清除css,js版本号 config.output.filename('static/js/[name].js').end(); config.out
  • webpack(v4.0.0以下)浅析

    2019-09-29 06:34:17
    // url-loader:和file-loader类似,不过他能将比limit小的图片转成base64,limit以上依然由file-loader来解析 module.exports = { module: { rules: [ { test: /\.(png|jpg|gif)$/i, ... ...
  • PHP 面试知识点整理归纳

    千次阅读 多人点赞 2019-01-25 17:17:32
    全文已整理补充完毕,以后还...lz也是初学者,以下知识点均自己整理且保持不断更新,也希望各路大神多多指点,若发现错误或有补充,可直接comment,lz时刻关注着。 由于内容比较多,没有直接目录,请自行对照 Gi...
  •  1 webpack简介  2webpack实现多个输入输出多个html  3webpack 中的module下rules 下的use和loader选项  4webpack 文件更新,如何使页面重新加载,而不是使用缓存,hash(版本号更新)  5webpack output 里面...
  • 2017年前端面试题整理汇总100题

    千次阅读 2018-03-01 16:46:43
    1.一些开放性题目1.自我介绍:除了基本个人信息以外,面试官更想听的是你与众不同的地方和你的优势。 2.项目介绍 3.如何看待前端开发? 4.平时是如何学习前端开发的?...5.未来三到五年的规划是怎样的?...
  • web面试题

    千次阅读 2018-03-02 10:46:07
    js实现浏览器缓存清除:①meta方法://不缓存&lt;META HTTP-EQUIV="pragma" CONTENT="no-cache"&gt; &lt;...Cache-Control"...no-cache, must-revalidate"... CON
  • 前言 去年年末研发组解散失业, so选择回去学车了,也顺利拿到了驾照 最近回归大深圳….开始踏上漫漫的找工作之路; “拉勾上吊一百年不匹配!!!”,”BOSS直聘日夜没反应!!!” 题目范围涵盖我最近... emm….....
  • 专题:Vue+Django REST framework前后端分离生鲜电商 Vue+Django REST framework 打造前后端分离的生鲜电商项目(慕课网视频)。 Github地址:... Django版本:2.2、djangorestframework:3.9.2。 前端Vu...
  • webpack配置

    2019-08-14 23:34:50
    webpack.config.js // webpack loader列表 // https://doc.webpack-china.org/loaders/less-loader // webpack plugin列表 // https://github.com/webpack-contrib/awesome-webpack#webpack-plugins const path = ...
  • webpack4+配置及优化

    2019-07-19 14:28:19
    1. 安装 首先安装webpack,参考...webpack通过webpack.config.js来配置,来看一下文件构造(zlpack可以忽略): 在webpack.config.js中基本的配置有: // 基于node的 遵循commonJS规范 let pa...
  • 上一篇 前端面试题(一)1. 你们公司有什么来项目监控阿里中间件ARMS前端监控和sourcemap产生的报错报给sensry2. 错误处理有哪些前端代码异常监控 前端相关数据监控 阿里巴巴(中国站)用户体验设计部博客(文中提到...
  • Webpack 是一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。 它的异步加载原理是,事先将编译好后的静态文件,通过js对象映射,硬编码进打包后...
1 2 3
收藏数 47
精华内容 18
关键字:

webpack 为chunk加随机数