具体webpack
的配置,戳这里
1、loader
css-loader
:解析css文件中的@import和url语句,处理css-modules,并将结果作为一个js模块返回style-loader
:将css-loader
解析后的内容以style标签的方式插入DOM树中less-loader
:将less编译为css,常搭配style-loader
使用style-loader
使用将 css-loader、style-loader 和 less-loader 链式调用,可以把所有样式立即应用于 DOM。
2、plugin
html-webpack-plugin
:可以根据模板自动生成html代码,并自动引用css和js文件HotModuleReplacementPlugin
:热更新compression-webpack-plugin
:生产环境可采用gzip压缩JS和CSShappypack
:通过多进程模型,来加速代码构建1、我们打包的时候,会先合并 Webpack config
文件和命令行参数,合并为options
。
2、将 options
传入Compiler
构造方法,生成compiler
实例,并实例化了 Compiler
上的 Hooks
。
3、compiler
对象执行run
方法,并自动触发beforeRun
、run
、beforeCompile
、compile
等关键 Hooks。
4、调用 Compilation
构造方法创建 compilation
对象,compilation
负责管理所有模块和对应的依赖,创建完成后触发 make Hook
。
5、执行compilation.addEntry()
方法,addEntry
用于分析所有入口文件,逐级递归解析,调用 NormalModuleFactory
方法,为每个依赖生成一个 Module
实例,并在执行过程中触发 beforeResolve
、resolver
、afterResolve
、module
等关键 Hooks
。
6、将第 5 步中生成的 Module
实例作为入参,执行 Compilation.addModule()
和 Compilation.buildModule()
方法递归创建模块对象和依赖模块对象。
7、调用seal
方法生成代码,整理输出主文件和 chunk
,并最终输出。
module.exports = {
resolve: {
mainFields: ['browser', 'module', 'main']
}
};
module.exports = {
resolve: {
mainFields: ['module', 'main']
}
};
为了减少搜索步骤,在明确第三方模块的入口文件描述字段时,我们可以将它设置得尽
量少。 由于大多数第三方模块都采用 main 宇段去描述入口文件的位置
resolve: {
mainFields: ['main'],
}
resolve: {
extensions: ['js', 'jsx','json'],
}
比如 require(’./data’),webpack会先去寻找data.js,如果美哟查找到,再去寻找data.jsx,再没有找到data.json后就会报错,没有该模块。
6. 优化 module.noParse 配置
让webpack忽略没有采用模块化的文件进行递归处理,提高构建性能。
watchOptions.poll
用于定义检查周期,也就是每秒检查多少次。watchOptions.aggregateTimeout
配置等待时间。目的是编辑代码的过程中高频输入文字,导致文件变化一直发生,每次重新构建就会卡死。watchoption: {
ignored: /node_modules/,
}
watchOption.aggregateTimeout
的值越大性能越好,降低重构频率watchOption.poll
的值越小越好,降低检查的频率自动刷新浏览器
webpack模块负责监听文件,webpack-dev-server负责刷新浏览器。
开启模块热替换
原理:
将多个页面的公共代码抽离为单独的文件,加入用户访问了某网站中的一个网页,那么访问其他网页的概率将非常大,在用户第一次访问后,这些页面的公共代码就会被浏览器缓存起来,在用户切换到其他页面时,就不会再重新加载存放公共代码的文件,而是从缓存中获取。
优点:
CommonsChunkPlugin
插件const CommonsChunkPlugin = require('webpack/lib/optimize/CommonChunkPlugin');
new CommonsChunkPlugin({
//从哪些chunk中提取
chunk: ['a', 'b'],
//提取后形成一个新的chunk
name: 'common'
});
new CommonsChunkPlugin({
//从哪些chunk中提取
chunk: ['common', 'base'],
//提取后形成一个新的chunk
name: 'base'
});
用户当前需要什么就只加载这个功能对应的代码。
1)将整个网站划分为一个个小功能,再按照每个功能的相关程度将它们分为几类。
2)将每一类合并为一个chunk,按需加载对应的chunk
3)不要按需加载用户首次打开网站时需要看到的画面所对应的功能将其放到执行入口所在的chunk中,以减少用户能感知的网页加载时间
4)对于不依赖大量代码的功能点,例如依赖Char.js去画图表,可再去对齐进行按需加载。
被分割出去的代码加载需要在一定的时机去触发,即当用户操作到了或者即将操作到对应的功能时再去加载对应的代码。被分割出去的代码的加载时机需要开发者根据网页的需求去确定。由于被分割出去的代码按需加载的过程也需要耗时,所以可以预估用户接下来可能会进行的操作,并提前加载对应的代码,让用户感受不到网络的加载。
例如在react-router中使用按需加载:
由于有大量文件需要解析和处理,所以构建是文件读写和计算密集型的操作, 特别是当章优化文件数量变多后, Webpack 构建慢的问题会显得更为严重。运行在 node. 之上的 Webpack 是单线程模型的,也就是说 Webpack 需要一个一个地处理任务,不能同时处理多个任务。
happy能够让Webpack做到这一点,它将任务分解给多个子进程去并发执行,子进程处理后将结果返回给主进程。
原理:
Compiler:
包含了所有webpack
的所有配置信息,包含option
|loaders
|plugins
,该对象有一个方法run
,执行该方法开始编译,全局只有一个
Compilation:
只要文件被修改,便有compilation
被创建,包含当前模块的资源、编译生成资源、变化文件
原来一个独立的模块文件被合并到了一个个单独的bundle.js
文件中,浏览器不能像node
快速加载本地文件,所以就将所有的模块放在一个数组中,执行一次网络请求。被加载过的文件不会执行第二次,执行结果会缓存在内存中。
还需要了解_webpack_require_
函数,定义在浏览器中执行的加载函数(模拟node.js
的require
)
import xxx from 'xxx'
呢?webpack内部的babel可以将es6的语法转换为CommonJs的语法。