最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 通过webpack偷偷搞点事情

    正文概述 掘金(Ez94450)   2021-01-29   342

    前言:随着项目的迭代,项目的代码量越来越大,客户端访问速度越来慢,此时webpack在优化打包体积和配合浏览器进行资源缓存上起到很大作用。

    首先要认识hash:

    众所周知webpack打包最终会通过output输出到指定目录下指定的文件名filename,如果filename写死成某个文件名,例如index.js,那么当此资源文件被客户端强缓存后,下次修改再次打包成index.js部署到server上,此时若server没有配置协商缓存,那么客户端会认为此资源没有被更新,从而会从本地强缓存取出index.js继续使用。这样就会遇到缓存问题。所以hash的作用就能发挥出来了。通过webpack的output可以配置如下生成唯一资源名称。

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

    webpack 内置了多种可使用的hash,按官网的解释分别如下:

    • hash:the hash of the module identifier 和整个项目的构建相关,只要项目文件有修改,整个项目构建的hash值就会改变
    • chunkHash:the hash of the chunk content 和webpack打包的chunk有关,不同的entry会生成不同的chunkhash值
    • contentHash:the hash of extracted content 根据文件内容来定义hash,文件内容不变,则contenthash不变

    注:hash的默认长度是20个字符,可以通过output.hashDigestLength全局配置,或使用[hash:8] 方式配置

    1.hash

    hash:配置好了hash可以发现每次修改代码后打包出来的资源文件名都不一样。但是如果不做任何修改,文件名可能会变,也可能不会变。官方的解释是:

    这也是因为 webpack 在入口 chunk 中,包含了某些样板(boilerplate),特别是 runtime 和 manifest。(译注:样板(boilerplate)指 webpack 运行时的引导代码)

    2.抽离boilerplate

    输出可能会因为当前的webpack版本而稍有差异,新版本不一定有和旧版本相同的hash问题。为了解决这个不稳定的因素,webpack4提供了一个配置可以把boilerplate给单独提取出来。

    optimization: {
    	runtimeChunk: {
    		name: 'manifest'
    	}
    }
    

    3.抽离第三方库

    如果不做处理,webpack会将我们引用到的第三方库和我们的源代码打包在一起。比较推荐的做法是将第三方库提取出来,输出到vendor chunk文件中,因为它们很少像本地源代码频繁改动。可通过以上方法配合浏览器的强缓存机制,来消除请求,减少客户向server获取资源次数。webpack很牛批的为我们提供了splitChunks。

        optimization: {
            splitChunks: {
                cacheGroups: {
                    vendor: {
                        test: /[\\/]node_modules[\\/]/,
                        name: 'vendors',
                        chunks: 'all',
                    }
                }
            }
        }
    
    manifest.js: 被注入了webpackJsonp的定义及异步加载相关的定义(webpack调用CommonsChunkPlugin处理后模块管理的核心,因为是核心,所以要第一个进行加载,不然会报错).
    
    vendor.js: 将所有从node_modules/里require(import)的依赖都打包到这里,所以这个就是所有node_modules/下的被require(import)的js文件
    
    main.js:项目中自己的代码
    

    4.模块标识符(module identifiers)

    项目中新增一个模块进行引用,再次构建,期望只有main bundle的hash发生改变。

    但是可以发现vendor的hash也变了,这是因为每个module.id会默认地基于解析顺序进行增量。当解析顺序发生变化,id也会随之变化。所以vendor的module.id发生了变化,从而也生成了新的hash。

    webpack提供了一个插件HashedModuleIdsPlugin

     plugins: [
         // 不再使用id作为打包模块的索引,采用文件路径的hash值
         new webpack.HashedModuleIdsPlugin()
     ]
    

    5.chunkhash

    虽然配置好了hash构建出来的所有模块hash都会变,但这是不利于缓存的。因为我可能只修改了一个chunk,另一个chunk没有修改

    chunkhash可以做到只针对修改的chunk生成hash,解决了hash的会对所有资源重新生成hash的痛点。

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

    6.css抽离

    用了chunkhash,看似是没问题了,其实项目中我们是需要把css代码抽离出来的。通常是用MiniCssExtractPlugin把css给单独提取出来

    new MiniCssExtractPlugin({
        filename: `[name].[hash].css`
    })
    

    7.contenthash

    css也是资源文件,也需要缓存。如果css使用hash生成的话,那么当某个模块引用了此css,但是css并没有修改。那重新打包出来的包中,css的hash也会随着重新生成。这很显然没有达到缓存的目的,我们是不希望没有改动的css资源名字被重新生成的。

    new MiniCssExtractPlugin({
        filename: `[name].[contenthash].css`
    })
    

    8.externals:外部扩展

    虽然上面通过splitChunks.cacheGroups为我们分离出了第三方库到vendor bundle中,但是我们希望将这些三方包从cdn引入,而不是将他打包。从cdn引入既可以加速客户访问速度,又可以进一步减小vendor打包体积。(下面只举例排除lodash库)

    externals: {
        lodash: '_'
    }
    

    9.写入cdn

    通过HtmlWebpackPlugin插件可以生成默认html页面,此时我们准备一个模板文件index.html,将externals掉的三方库通过cdn引入进去,(下面只举例lodash,其他三方库可自行再次引入)

    <body>
    	<script type="text/javascript" src='https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js' crossorigin></script>
    </body>
    
    plugins: [
    	...,
    	new HtmlWebpackPlugin({
    		template: path.resolve(__dirname, './index.html')
    	})
    ]
    

    起源地下载网 » 通过webpack偷偷搞点事情

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元