1. 全网最贴心webpack系列教程和配套代码
2. webpack4系列教程
3. webpack - babel配置
4. 没有了CommonsChunkPlugin,咱拿什么来分包
5. webpack.config.js配置遇到Error: Cannot find module '@babel/core'问题
6. NPM install -save 和 -save-dev 傻傻分不清
7. 怎么理解webpack中的output.filename 和output.chunkFilename
8. webpack4——SplitChunksPlugin使用指南
9. Webpack4之SplitChunksPlugin规则
10. SplitChunksPlugin
先看 第三篇.
下载
npm install --save-dev babel-loader babel-core babel-preset-env
配置
原文
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
['env',{
targets: {
//targets是presets的一些预设选项,这里表示将js用于浏览器,只确保占比大于1%的浏览器的特性,主流浏览器的最新两个主版本。(没听懂)
browsers: ['> 1%', 'last 2 versions']
}
}]
]
}
},
//定义不希望babel处理的文件
exclude: '/node_modules/'
}
]
}
报错
我写成这个样子
{
test : /\.js$/,
use : [
loader : "babel-loader",
options : {
presets : [
['env',{
target : {
browsers : ['>1%','last 2 versions']
}
}]
]
}
],
exclude :'/node_modules/'
}
改一下
{
test : /\.js$/,
use : [{
loader : "babel-loader",
options : {
presets : [
['env',{
target : {
browsers : ['>1%','last 2 versions']
}
}]
]
}
}
],
exclude :'/node_modules/'
}
还是报错
改成原文粘贴,还是报同样的错.
仔细看了一下错误信息,似乎是说, 版本不太对.
果断百度
webpack.config.js配置遇到Error: Cannot find module '@babel/core'问题
果然是版本问题
低版本,
npm install -D babel-loader@7 babel-core babel-preset-env
最新版本
npm install -D babel-loader @babel/core @babel/preset-env webpack
我用了第二种下载
发现package.json中
"@babel/core": "^7.1.6",
"@babel/preset-env": "^7.1.6",
"babel-core": "^6.26.3",
"babel-loader": "^8.0.4",
"babel-preset-env": "^1.7.0",
然后用 uninstall 删除了 "babel-core": "^6.26.3", "babel-preset-env": "^1.7.0",
结果报错
字面意思是还要重新下 "babel-preset-env"?
闹心.. 删了,重新用低版本的语句.
成功..
测试用 .bablerc
这是个什么意思? 是文件名,还是文件格式? 他说的是json格式.
创建一个 bablerc.json文件 在根目录中.
反正效果是正常出现, 但不知道是不是正常把 es6改成es5了啊..
babel-polifill插件
首先这是个插件..
说是什么垫片, 什么是垫片?
咦,他说 babel-polifill插件有缺陷,全局污染什么的.
用 runtime-transform插件
安装
npm install --save-dev babel-plugin-transform-runtime
npm install --save babel-runtime
疑问,-g 是全局, --save-dev 我知道是 开发环境, --save是什么?
NPM install -save 和 -save-dev 傻傻分不清
明白了
就是生产环境和开发环境的区别.
标记为开发环境的包,是指,我建立项目需要用到的工具,
项目完成后,这些工具对项目的运行是没有必要的.
而标记为生产环境的包,是指,项目最后运行时,需要的包.
如果把 --save 的写成 --save-dev 那最后可能项目用不了?
如果把 --save-dev 写成 --save 那项目就拥有了没用的很多东西?
回到正题,
在bablerc 文件中放入
{
"plugins": ["transform-runtime"]
}
报错
改回了,就是位置放错了,要放在preset 同级的位置上.
webpack4 系列教程(三): 多页面解决方案--提取公共代码
先跟着读一遍
然后试着写一遍.
问题1. chunkFilename是什么?
怎么理解webpack中的output.filename 和output.chunkFilename
webpack中output配置项中chunkFilename属性的用法
大意是说, 异步加载的模块,不会按照filename 的规则生成文件名?
会按照 chunkFilename 的规则生成文件名?
似乎多用于 这种情况?
require.ensure([],function(require){alert(11);require('./greeter')})
require.ensure(["modules/tips.jsx"], function(require) {
var a = require("modules/tips.jsx");
// ...
}, 'tips');
require.ensure的用法;异步加载-代码分割
问题2 optimization.splitChunks 是什么?
没有了CommonsChunkPlugin,咱拿什么来分包
感觉写的很详细,很牛逼, 但看得我脑瓜疼.
他要是配些图就好了.
首先理解他的配置和效果的因果关系之前,
我首先要理解他要解决的是什么? 他要解决什么需求?
我觉得是这样的.
我们写完源代码,用webpack打包,生成最终文件.
假设默认最终只生成一个文件?
那这个文件肯定太大了,用户发送请求获取的时候,
解析后渲染一定会很慢啊.
所以,起码应该把 img 这种资源要分割开来.
还有一些资源,js代码,我们希望是按需加载,
这一部分的代码,我们也应该分割开来.
假设我们的服务器上存在多个页面,
那这几个页面必然是不同的文件,
而这些页面的js,或者其他资源,有可能是共用的.
或者可以说,我们应该把这些文档中,
重复的部分抽离分割成独立的文件,
比如 common.
假设,以上是我们打包后的分割需求(估计还有其他原因的分割需求)
第一种方案是,
我们在写源文件的时候,
就可以按照最终的逻辑写文档.
然后让该独立的文档,不要被合成进去.
但我们知道,有--save 的部分,
也就是,我最终的代码当中,有依赖其他一些包,
也就是那个什么node_modules中的包
这些包应该也要根据情况分包.
根据昨天学的知识, 我接触的分包有以下几种,
第一种是 loader
img 文件, 用 url-loader 设置 limit, name
第二种是plugin
html-webpack-plugin 独立生成html 包
mini-css-extract-plugin 独立生成 css 包 似乎会把所有scss css 文件都打包成一个?
怎么对 js 文件进行分包没接触,
也就是,如果有多个入口文件, 就对应生成对个出口文件?
作为一个小白没什么经验的我来讲,以上就是我仅有的理解了.
现在,我们重新看一下上面的 分包博客
影响理解的词汇,概念
chunk : 代码块
on-demand 按需加载
初始代码块 : 什么是初始代码块?
百度搜索出另一篇博客
深入 webpack 打包机制的介绍
这是从webpack 各个版本进化的角度讲的,没能完全看懂,但很牛逼.
// 这个代码的含义是,在这些入口文件中,找到那些 ***引用两次的模块***
//(如:utilB), 那么 utilB 会抽离成一个叫 vendor 文件。此时那部分初始化工作的代码会被抽离到 vendor 文件中。
new webpack.optimize.CommonsChunkPlugin({
// 最后生成的文件名?
name: "vendor",
// 被引用的次数?
minChunks: 2
});
// 这段代码的含义是在 vendor 文件中帮我把初始化代码抽离到 mainfest 文件中,
//此时 vendor 文件中就只剩下 utilB 这个模块了,那么我们为什么需要这么做呢?你可能会有这样的问题
new webpack.optimize.CommonsChunkPlugin({
// 生成的文件名?
name: "manifest",
// 选择哪个代码块
chunks: ["vendor"]
// 被重复引用的次数为无限?
// minChunks: Infinity 可写可不写
});
独立分割一些不常变动的,有利于缓存?
什么是 长期缓存策略?
看一下这一段话
webpack根据下述条件自动进行代码块分割:
- 新代码块可以被共享引用,OR这些模块都是来自node_modules文件夹里面
- 新代码块大于30kb(min+gziped之前的体积)
- 按需加载的代码块,最大数量应该小于或者等于5
- 初始加载的代码块,最大数量应该小于或等于3
为了满足后面两个条件,webpack有可能受限于包的最大数量值,生成的代码体积往上增加。
理解:
- 只要是 node_modules里的文件就 分割成独立包
- 只要是被不同代码多次共享, 就分割成独立包
- 只要是 被加载的代码块 过大(大于 30kb) 就分割成独立包.
前三个好理解 - 按需加载的代码块, 最大数量 <= 5 时, 分割成独立包?
指的是按需加载的代码块的数量嘛?
按需加载的代码块,指的是异步加载的代码块?
5.初始加载的代码块的数量 <= 3?
什么是初始加载的代码块? 同步加载的?
(这就是强烈需要一个老师的时候,对这个作者来讲,这个概念,以及指向什么东西
是非常明显的,可到了我这,就要费很多时间要去猜,好浪费,好心疼)
我们看一下他举的两个例子
// entry.js
import("./a");
// a.js
import "react-dom";
他说
结果:webpack会创建一个包含react-dom的分离代码块。当import调用时候,这个代码块就会与./a代码被并行加载。
为什么会这样打包:
条件1:这个代码块是从node_modules来的
条件2:react-dom大于30kb
条件3:按需请求的数量是2(小于5)
条件4:不会影响初始代码请求数量
条件1.条件2 听懂了, 条件3 按需请求的数量是2 是个什么鬼?
这个2是怎么来的?
现在的假设是这样的,
入口文件是一个包,
react-dom 也是一个包,
这俩并非直接依赖, 所以算是异步依赖,
并行的数量是 2, 所以是2?
条件4 的不会影响初始代码请求数量又是 什么鬼?
现在的假设是这样的.
初始代码,也就是入口文件 依赖的是 a.js
但a.js 并不会被独立分包, 也就说, 入口文件
依赖的包当中 被独立分包的个数.
什么是初始代码块?
inital chunks,,没百度出来.
我只能假设为,一个入口文件就是一个初始代码块,
尽管他引入了几个代码块, 但初始代码块只有一个? 所以没有影响?
如果这也是和条件3一样类型的限制条件,
那么有就是存在这种可能,
如果满足条件1和条件2 进行了分包, 就有可能会增加初始代码的请求数量?
但到底怎样的分包情形才会出现这种情况呢?
继续读博客,
有四个选项可以用于配置这些条件:
- minSize(默认是30000):形成一个新代码块最小的体积
- minChunks(默认是1):在分割之前,这个代码块最小应该被引用的次数(译注:保 证代码块复用性,默认配置的策略是不需要多次引用也可以被分割)
- maxInitialRequests(默认是3):一个入口最大的并行请求数
- maxAsyncRequests(默认是5):按需加载时候最大的并行请求数。
咦? 你发现这几个参数和 上面的四个条件是一一对应的.
minSize = 30000 对应的是 超过30k 就分包
minChunks = 2 如果被引用次数 超过 2次就 分包?
maxIntialRequesets = 3 入口最大的并行请求数?
总算找到了 关键词, 果断搜索
webpack optimization 里的 maxInitialRequests 配置项是啥意思?
如果配置了 runtimeChunk(将webpack runtime单独抽离出来),那么maxInitialRequest就是代码分割以后,除去runtime所能生成的最多脚本数目
否则是就是能生成的最多脚本数目
splitChunks: {
chunks 有三个值, "all","initial","async"
文档说 all 的时候 async 块和 non-async 块 可以共享代码块,
inital 应该是指 入口文件 相关的 non-async块,也就是同步加载的代码块.
async 应该是指 异步加载的代码块.
chunks: "async",
大小超过30000 时分包
minSize: 30000,
最少被引入的次数.
minChunks: 1,
谷歌翻译是: 按需加载时的最大并行请求数。
我觉得应该是指, 不是入口文件直接引入的文件,
被分包的个数要小于5个 , (5 个当中 应该算上 入口文件?)
maxAsyncRequests: 5,
谷歌翻译是: 入口点处的最大并行请求数。
我觉得应该是指, 入口文件直接引入的文件中,
被分包的个数要小于3个,
如果大于3个就不进行分包.
maxInitialRequests: 3,
实际上,上面这两个属性这么解释的话,
似乎和以前学习的异步加载的概念对不上..
异步应该只的是 import.aysnc,import.then,require(a.js",function(){})
name 为 true 时,自动生成名字?
name: true,
cacheGroups:缓存组// 上面这几个属性会默认作用在下面,或者缓存组也可以单独设置上面的选项
cacheGroups: {
default 缓存组是, 只要被 引用两次或两次以上的代码
default: {
最少被重复引用的次数为2
minChunks: 2,
优先级, 优先级越高, 表示 优先进行打包.
priority: -20,
表示, 有同样的包 再次遇到时,不会产生新的包, 而是引入已经有打包的包?
reuseExistingChunk: true,
},
node_modules 里引入的包,默认会放进verdors,默认分包,
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
}
}
SplitChunksPlugin
哎呀妈呀,搜索不出来, 搜出英文文档的页面.
话说,这个倒是真的全,看来以后真的要多接触英文文档了.
反正有谷歌网页翻译.还是接触第一手资料比较有效率.
webpack4——SplitChunksPlugin使用指南
这位大神总结的也很清晰啊.
不过看了这么文章, 大概的概念都了解了,
就是那两个 ,按需加载最大请求次数,初始化加载最大请求次数
到底是个什么鬼还是不确定,不清晰.
果然尼玛,我的假设是错的,
看另一个大神
Webpack4之SplitChunksPlugin规则
这位大神也是对这两个概念产生疑问, 然后进行了测试,结论是
之前我认为是webpack根据代码结构自行分割(split),后来发现并非如此,这其实涉及到代码中动态加载(on demand loading)组件的概念
可见业务2相关的代码由webpack4生成的runtime chunk来需要的时候动态引入
(这里明白一件事情,想要完成动态加载,就必须有 runtime chunk)
(所谓的动态引入就是按需加载,就是最终按需异步加载的部分.)
maxAsyncRequests(最大的异步请求数)和maxInitialRequests(最大的初始请求数是为了防止chunk划分的过于细致,导致大量的文件请求降低performance)。
还从上一次分包情况入手分析:vendors-index和vendors-main都是来自node_moudules。那么当前按需加载的代码块的并行请求数就是2。
(这里就不太明白了,为什么都来自node_modules的文件就会被判定是按需加载的代码块?不对吧?)
设置maxAsyncRequests=1 可以看到,index和main还在,但是verdors只剩下了vendors~main chunk。可见按需加载(chunks on demand)的代码块指的就是vendors~chunk
(这里保留意见, 按需加载的代码块指的可能不是 venders~chunk, 而是runtime.js?
又或者是 入口文件本身?)
maxInitialRequests 指的是模版html文件中,并行请求的javascript(不包括runtime)的数量。
(我上面的猜测少了这个runtime ,整个图谱缺了一块,自然想不明白)
--
maxInitialRequests 是 最后在index.html文件中,除了 runtime.js
之外引入的