前段时间一直在基于webpack进行前端资源包的瘦身。在项目中基于路由进行代码分离,http://www.cnblogs.com/legu/p/7251562.html。但是打包的文件还是很大,特别是通过CommonsChunkPlugin的async:true打包的chunk的公共包不可控。今天就通过CommonsChunkPlugin插件的理解,来优化这个问题

  问题描述详细些,我们的打包是基于router进行的chunk分割,比如router有10个,router1,router2用到了echart,所以echart打包到了公共文件async中。但是如果用户通过链接,

  第一次直接访问的router3,这样就会先加载公共文件async,可是echart代码其实是多余的,影响到了router3的展现。

  一开始遇到这个问题,没想到太好的方法,让echart基于chunk进行按需打包~~实在没办法,最后只能从CommonsChunkPlugin插件的源代码入手,看看有什么启发。

  

     apply(compiler) {
compiler.plugin("this-compilation", (compilation) => {
compilation.plugin(["optimize-chunks", "optimize-extracted-chunks"], (chunks) => {
/**
* 根据chunkNames[options.name, options.names],从chunks中筛选出targetChunks, 没有则使用compilation.addChunk新增
* 如果children || async,返回targetChunks = chunks
*/
const targetChunks = this.getTargetChunks(chunks, compilation, this.chunkNames, this.children, this.async);
targetChunks.forEach((targetChunk, idx) => {
/**
* 根据selectedChunks【options.chunks】,从chunks筛选出affectedChunks
* async || children,返回 affectedChunks = targetChunk.chunks, 如果children = true,进行深度遍历
*/
const affectedChunks = this.getAffectedChunks(compilation, chunks, targetChunk, targetChunks, idx, this.selectedChunks, this.async, this.children, this.deepChildren);
let asyncChunk;
if(this.async) {
//如果async==string,进行name筛选
asyncChunk = affectedChunks.filter(c => c.name === this.async)[0];
if(!asyncChunk) {
/**
* 根据async创建一个新的chunk,和targetChunk绑定关系
* asyncChunk.addParent(targetChunk); targetChunk.addChunk(asyncChunk);
*/
asyncChunk = this.createAsyncChunk(
compilation,
targetChunks.length <= 1 || typeof this.async !== "string" ? this.async :
targetChunk.name ? `${this.async}-${targetChunk.name}` :
true,
targetChunk
);
}
targetChunk = asyncChunk;
}
// 根据minChunks的设置,遍历affectedChunks的modules,返回符合条件的公共modules集合
const extractableModules = this.getExtractableModules(this.minChunks, affectedChunks, targetChunk);
if(this.minSize) {// minSize限制逻辑
const modulesSize = this.calculateModulesSize(extractableModules);
if(modulesSize < this.minSize)
return;
}
// affectedChunks中移除extractableModules中modules的关系,只返回存在公共modules的Chunks集合(removeChunk返回true)
const chunksWithExtractedModules = this.extractModulesAndReturnAffectedChunks(extractableModules, affectedChunks);
// 公共的modules 和 targetChunk 绑定关联关系
// chunk.addModule(module); module.addChunk(chunk);
this.addExtractedModulesToTargetChunk(targetChunk, extractableModules);
if(this.filenameTemplate)
targetChunk.filenameTemplate = this.filenameTemplate;
if(this.async) {
//被移除modules的Chunk,设置和targetChunk的关系,需要第一个加载targetChunk才能加载chunksWithExtractedModules
this.moveExtractedChunkBlocksToTargetChunk(chunksWithExtractedModules, targetChunk);
asyncChunk.origins = this.extractOriginsOfChunksWithExtractedModules(chunksWithExtractedModules);
return;
}
//设置affectedChunks和targetChunk的parent关系
this.makeTargetChunkParentOfAffectedChunks(affectedChunks, targetChunk);
});
return true;
});
});
}

  代码逻辑不是很复杂,主要是chunks之间的关系和chunks与modules之间的关系该怎么去维护,对于不清楚webpack打包机制的人,很难一时间了解。其实我也不很了解。

  根据上面我的中文注释,对大家的了解有一些帮助。我们会发现,对我们的问题没有什么直接关系。

  回到我们的问题,异步的模块中,共用模块怎么能再进行拆分,把大模块echarts,ace编辑器等进行分开打包,并且能自己处理关系,需要的时候才异步加载进来?

  其实最后问题的答案很简单,需要实现自动异步加载,那肯定还是要借助CommonsChunkPlugin的async,我们可以根据实际情况,通过minChunks,把echarts,ace这种大库先进行一次async打包,这样再进行根据router的async打包的时候,自然不会再有echarts,ace了,看下现在的配置

         new webpack.optimize.CommonsChunkPlugin({
names: ['vendor', 'libs', 'manifest']
}),
new webpack.optimize.CommonsChunkPlugin({
async: 'brace',
minChunks: function(module, count) {
var path = `/public/node_modules`;
var resource = module.resource;
if ( resource &&
(
resource.indexOf(`${path}/_brace`) !== -1 ||
resource.indexOf(`${path}/brace`) !== -1
)
) {
return true
}
return false;
}
}),
new webpack.optimize.CommonsChunkPlugin({
async: 'echarts',
minChunks: function(module, count) {
var path = `/public/node_modules`;
var resource = module.resource;
if ( resource &&
(
module.resource.indexOf(`${path}/_echarts`) !== -1 ||
module.resource.indexOf(`${path}/echarts`) !== -1 ||
module.resource.indexOf(`${path}/zrender`) !== -1 ||
module.resource.indexOf(`${path}/_zrender`) !== -1
)
) {
return true
}
return false;
}
}),
new webpack.optimize.CommonsChunkPlugin({
async: 'async',
minChunks: 2
}),

  

基于CommonsChunkPlugin,webpack打包优化的更多相关文章

  1. Webpack 打包优化之速度篇

    在前文 Webpack 打包优化之体积篇中,对如何减小 Webpack 打包体积,做了些探讨:当然,那些法子对于打包速度的提升,也是大有裨益.然而,打包速度之于开发体验和及时构建,相当重要:所以有必要 ...

  2. Webpack 打包优化之体积篇

    谈及如今欣欣向荣的前端圈,不仅有各类框架百花齐放,如Vue, React, Angular等等,就打包工具而言,发展也是如火如荼,百家争鸣:从早期的王者Browserify, Grunt,到后来赢得宝 ...

  3. (webpack系列二)webpack打包优化探索

    虽然webpack的已经升级到了webpack4,而我们目前还在使用webpack3,但其中的优化点都大同小异,升级后同样适用. 性能优化初步原则 减小代码量 减小请求数 最大化利用浏览器缓存 这三条 ...

  4. webpack打包优化之外部扩展externals的实际应用

    目录 前言 externals定义 用法 string array object function regex 实际案例 打包时间 打包之后包的大小 浏览器加载 需要注意 参考 前言 使用vue-cl ...

  5. 记一次webpack打包优化

    未进行打包优化的痛点: 随着项目的不断扩大,引入的第三方库会越来越多,我们每次build的时候会对所有的文件进行打包,耗时必定很长,不利于日常开发. 解决思路: 第三方库我们只是引入到项目里来,一般不 ...

  6. [转] Webpack 打包优化之体积篇

    谈及如今欣欣向荣的前端圈,不仅有各类框架百花齐放,如Vue, React, Angular等等,就打包工具而言,发展也是如火如荼,百家争鸣:从早期的王者Browserify, Grunt,到后来赢得宝 ...

  7. webpack打包优化并开启gzip

    应用场景:项目使用webpack2.x进行打包,打包后静态资源通过nginx转发配置: 问题:webpack打包后的资源文件特别,特别大,没打包之前页面一个页面js有2M左右(其中已经抽离了css)? ...

  8. webpack 打包优化的四种方法(多进程打包,多进程压缩,资源 CDN,动态 polyfill)

    如今,webpack 毫无疑问是前端构建领域里最耀眼的一颗星,无论你前端走哪条路线,都需要有很强的webpack 知识.webpack 的基本用法这里就不展开讲了.主要探讨一下如何提高 webpack ...

  9. webpack打包优化点

    目录 1. noParse 2. 包含和排除目录 3. IgnorePlugin 4. happypack 5. DllPlugin动态链接库 6. 热更新 7. 开发环境 tree-shaking ...

随机推荐

  1. js基础之DOM中元素对象的属性方法

    在 HTML DOM (文档对象模型)中,每个部分都是节点. 节点是DOM结构中最基本的组成单元,每一个HTML标签都是DOM结构的节点. 文档是一个    文档节点 . 所有的HTML元素都是    ...

  2. K8S调度之节点亲和性

    Node Affinity Affinity 翻译成中文是"亲和性",它对应的是 Anti-Affinity,我们翻译成"互斥".这两个词比较形象,可以把 po ...

  3. 学习Oracle的一些收获

    前言: 在看尚硅谷的Oracle视频时,总结的一些自己之前不熟的,或者完全不了解的知识点,只适用于本人,本人有一定的SQL基础,所以一些我比较熟悉的知识点不会列出来. Oracle中SQL使用技巧: ...

  4. 博世传感器调试笔记(一)----加速度传感器BMA253

    公司是bosch的代理商,最近一段时间一直在公司开发的传感器demo板上调试bosch sensor器件.涉及到的器件有7,8款,类型包括重力加速度.地磁.陀螺仪.温度.湿度.大气压力传感器等.在调试 ...

  5. N制和PAL制区别

  6. go build 不同系统下的可执行文件

    Golang 支持在一个平台下生成另一个平台可执行程序的交叉编译功能. 1.Mac下编译Linux, Windows平台的64位可执行程序: 1 2 $ CGO_ENABLED=0 GOOS=linu ...

  7. 介绍一个基于jQuery的Cookie操作插件

    在网页客户端,我们经常会遇到读取或者设置cookie的情况,如果用纯生的js我们可能会遇到一些兼容性带来的麻烦,这里给大家介绍一个比较实用jquery操作cookie的插件,插件的源代码如下: jQu ...

  8. IE10下 FormsAuthentication.SetAuthCookie无效的问

    问题是这样的,我在本地测试设置身份验证票据都没问题,发布到服务器后访问地址添加了一些特殊的字符,看起来像加过密的,如下: http://www.example.com/(F(1xe9eXIxPzMAL ...

  9. input必填

    <li> <span>出生日期</span> <div style="margin-left: 1.5rem;"> <inpu ...

  10. C++中的二级指针和指针引用函数传参

    在函数的使用过程中,我们都明白传值和传引用会使实参的值发生改变.那么能够通过传指针改变指针所指向的地址吗? 在解决这个问题之前,也许我们应该先了解指针非常容易混淆的三个属性: ①.指针变量地址(&am ...