1、loader和plugin的区别:loader处理不同类型的文件;plugin作用于整个打包过程
2、常见的loader:
- css相关:css-loader,style-loader,less-loader,file-loader等
- js:babel-loader,babel是js编译器,能够将es新版本的语法编译成浏览器可识别的语法。@babel/polyfill 全局垫片,将es6中的promise变为全局变量,规范化,转化到浏览器兼容的标准。可通过如下配置实现按需加载。
.babelrc
{
"presets": [
["@babel/preset-env", {
// 按需注入
"useBuiltIns": "usage",
}]
]
- polyfill会污染全局对象(开发library不推荐使用),可以使用babel-plugin-transform-runtime
3、配置出口文件名称中[hash]:只要重新打包,所有hash值都改变,所有文件hash值一样;[chunkhash]:根据不同的入口文件(Entry)进行依赖文件解析、构建对应的chunk,生成对应的哈希值。比如在生产环境里把一些公共库和程序入口文件区分开,单独打包构建,接着我们采用chunkhash的方式生成哈希值,那么只要我们不改动公共库的代码,就可以保证其哈希值不会受影响;[contenthash]:内容没修改时不改变hash值,css单独打包时推荐使用(比如js文件发生变化,其引入的css单独打包后hash值也会变化,配置contentHash后则不会发生变化)
3、性能优化
- loader中使用exclude/include/test限制打包范围
- moduler.resolve设置查找文件的路径
- alias设置别名
- extensions在文件引入没有写后缀时自动匹配
- cdn 使用externals优化cdn资源
- 压缩打包文件体积,带宽小,用户加载快optimize-css-assets
- tree-shaking 摇树,死代码,引入未使用,js摇树只支持esmodule,可通过配置限制部分文件不用摇树(比如css文件引入但是在js中未使用会被摇掉,导致不生效)
- 代码分割:多个页面使用公共模块时,将公共模块抽离,公共文件只需下载一次
- 魔法注释,打包后显示文件名,在首屏加载时,用到哪个模块再加载哪个模块,实现懒加载进行页面的优化。profetch:浏览器空闲时 preload并行
const router = new Router({
routes: [
{
path: "/home",
component: () => import(/* webpackChunkName: "home"*//* webpackPrefetch: true */ '@/views/home'),
meta: { type: '首页' }
}
],
});
- concatenateModule 作用于提升,减少闭包数量,加快js执行
- dllplugin 动态链接库,本质为缓存,提升打包速度,不能减少体积,优化开发体验;把网页依赖的基础模块抽离出来,当需要导入的模块存在于某个dll中时,这个模块不再被打包,而是从dll中获取;例如Vue等版本较为固定不需要每次打包,打包时告诉webpack不要每次都构建,借助dllreferencePlugin告诉webpack有哪些依赖有dll,借助dll生成dll动态文件,minifest第三方库映射
- hardSourcewebpackplugin 硬件加速后续构建速度
- happywebpack并发构建,将文件解析任务分解成多个子进程,子处理完后将结果发送给主进程作用于loader,复杂的大中型项目使用,小项目不适用
4、各种环境下使用不同的配置,使用webpack-merge进行合并,设置环境变量的两种方式,一是直接set NODE_ENV='production',会存在各种环境不兼容问题;二是使用cross_env,cross_env NODE_ENV='production'5、
5、创建一个webpack
1、接收一份配置文件(webpack.config.js)
2、分析出入口模块位置
- 读取入口模块的内容,分析内容
- 分析哪些是依赖,哪些是源码(es6.jsx等需要处理浏览器才能执行)
- 分析其他模块
3、拿到对象数据结构
- 模块路径
- 处理好的内容
4、创建bundle.js
- 启动器函数,来补充代码里可能出现的module,exports,require,让浏览器能够顺利执行