前端性能优化(分包打包)

当前问题是:webpack2默认配置打包(将使用到的node_modules第三方架包)打到一个文件vendor中去了,导致首屏加载文件大、速度非常慢;所有的业务代码将打包到index文件中,对于多业务或复杂业务场景,均会使得打包出来的index文件非常大,从而导致首页加载速度慢。

当然webpack3+版本,它自身已做了分包,不需要再做分包处理了,因此下面所涉及的内容均只针对webpack2版本,下面将对上述index、vendor两个文件分别进行分包处理。

(1) 第一步,webpack.test.conf.js中,生成manifest.js文件
new webpack.optimize.CommonsChunkPlugin({
   
name: 'manifest',
   
filename: 'manifest.js'
})

(2) 第二步在webpack.test.conf.js中 添加如下代码,chunksPackage即对使用到的node_modules第三方架包进行分包处理,降低打包后vendor文件的大小;并将业务router拆分成两个(或多个)单独的路由,并抽取成common文件,分别单独进行打包来降低index文件的大小。

// 需要chunks的包列表,支持正则
let chunksPackage = {
	'jquery':/jquery/,
	'element': /element-ui/,
	'vue':/vue/
}
function getModuleName(module) {
	var sign = 'node_modules';
	var signIndex = module.resource.indexOf(sign);
	var pathSeparator = module.resource.slice(signIndex - 1, signIndex);
	var modulePath = module.resource.substring(signIndex + sign.length + 1);
	var moduleName = modulePath.substring(0, modulePath.indexOf(pathSeparator) );
	moduleName = moduleName.toLowerCase();
	return moduleName
}

 plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            minChunks: function(module, count) {
                return (
                    module.resource &&
                    /\.js$/.test(module.resource) &&
                    module.resource.indexOf(
                        path.join(__dirname, '../node_modules')
                    ) === 0
                )
            }
        }),
	    ...Object.keys(chunksPackage).map(packageName => {
		    return new webpack.optimize.CommonsChunkPlugin({
			    name: packageName,
			    chunks: ['vendor'],
			    minChunks: function(module, count) {
				    return module.resource && 
                    chunksPackage[packageName].test(module.resource)
			    }
		    })
	    }),
	    new webpack.optimize.CommonsChunkPlugin({
		    name: '_common',
		    chunks: ['index','_router']//index.js和_router.js中抽取_common
	    }),
	    new webpack.optimize.CommonsChunkPlugin({
		    name: 'common_',
		    chunks: ['index','router_']//index.js和router_.js中抽取common_
	    }),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'manifest',
	        filename: 'manifest.js'
        }),
]

(3) 第三步修改utils文件,调整打包后的js文件在页面中的引用顺序

// 多入口配置
// 通过glob模块读取pages文件夹下的所有对应文件夹下的js后缀文件,如果该文件存在
// 那么就作为入口处理
exports.entries = function() {
    var entryFiles = glob.sync(PAGE_PATH + '/*/*.js');
    var map = {};
    entryFiles.forEach((filePath) => {
        var filename = filePath.substring(filePath.lastIndexOf('\/') + 1, 
                       filePath.lastIndexOf('.'));
        var jsarr = (filename=='_router'||filename=='router_')?[]
                    :['babel-polyfill'];
	    jsarr.push(filePath);
        map[filename] = jsarr;
    });
    return map
}
// 多页面输出配置
// 读取pages文件夹下的对应的html后缀文件,然后放入数组中
exports.htmlPlugin = function() {
    let entryHtml = glob.sync(PAGE_PATH + '/*/*.html')
    let arr = []
    entryHtml.forEach((filePath) => {
        let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, 
                       filePath.lastIndexOf('.'));
        let tempChunks = ['manifest','vue','jquery', 'element', 
                          'vendor','_common','common_','_router',
                          'router_',filename];
        let conf = {
            template: filePath,
            filename: filename + '.html',
            chunks: tempChunks,
            inject: true,
	        chunksSortMode: function (chunk1, chunk2) {
		        let order1 = tempChunks.indexOf(chunk1.names[0]);
		        let order2 = tempChunks.indexOf(chunk2.names[0]);
		        return order1 - order2;
	        }
        }
        if (process.env.NODE_ENV === 'production') {
            conf = merge(conf, {
                minify: {
                    removeComments: true,
                    collapseWhitespace: true,
                    removeAttributeQuotes: true
                },
                chunksSortMode: 'dependency'
            })
        }
      arr.push(new HtmlWebpackPlugin(conf))
    })
    return arr
}

(4) 第四步在webpack.base.conf.js中添加如下配置

plugins: [
   new webpack.ProvidePlugin({
      $:"jquery",
      jQuery:"jquery",
      "windows.jQuery":"jquery"
   })
]

完成上述步骤后,打包后的vendor文件将在原基础上降低700多KB,打包后的index文件将在原基础上降低至少一半以上,具体效果见下图。

分离所有使用中的第三方node_modules包,只需在chunksPackage添加需要分离的第三方架包名称即可;业务分包则需要,首先在plugins中配置CommonsChunkPlugin,其次在htmlPlugin 中配置chunks,调整对应包在html的引用顺序。

此外根据上述方法,vendor和index均可无限拆分,vendor拆分极限即使用中的node_modules中最大的那个架包,index拆分极限即路由中最大的那个路由。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值