1. webpack的基本概念
- mode 模式(4.0开始)
- entry入口
- output输出结果 经过一系列的处理得到的最终结果
- loader加载器 webpack只识别js 其他模块通过loader做转换
- plugin 扩展插件 在特定时机可以注入处理逻辑 工作流
- module模块(webpack中一切模块)chunk代码块(多个模块组成chunk)
2. 与webpack类似的工具有哪些
- grunt(自动化 压缩编译) glup(基于node的steam流打包 通过task构建)
- rollup(js类库打包)
- parcel(快速 0配置 webpack5支持0配置)
- vite(基于esModule实现) koa各种中间件(搭建静态服务 通过import路径进行重写)
3. loader和plugin的区别 常见的loader和plugin有哪些
- loader是加载器 webpack将一切文件视为模块 但是原生只能解析js文件 如果想打包其他文件就需要loader。loader的作用就是将webpack拥有了加载和解析非js文件的能力
- plugin是插件 可以扩展webpack的功能 在webpack运行的生命周期中会广播许多事件 plugin可以监听这些事件 在合适的时机通过webpack提供的api改变输出结果
// babel-loader用来转换js代码 很慢 通过cache和exclude来提高速度
// @babel/core是babel的核心库 需要用一些插件(plugins)来实现功能 presets是一系列插件的集合
npm install babel-loader @babel/core @babel/preset-env @babel/preset-react -D
npm install eslint-loader -D // pre loader的执行顺序
// 样式相关 注意loader执行顺序 loader的单一功能职责
npm install css-loader style-loader less less-loader sass sass-loader node-sass -D
npm install postcss-loader px2rem-loader autoprefixer
npm install mini-css-extract-plugin -D // 插件 将css文件单独抽取
// 文件相关 image-webpack-loader可以对图片进行压缩处理
npm install file-loader url-loader image-webpack-loader -D
html-webpack-plugin 我们可以监听这个插件提供的hook实现很多功能
mini-css-extract-plugin 抽取css文件
copy-webpack-plugin
clean-webpack-plugin
// 压缩 webpack内置
terser-webpack-plugin // uglify不支持es6
optimize-css-assets-webpack-plugin // 压缩css文件
// 分析相关的
npm install webpack-bundle-analyzer speed-measure-webpack-plugin -D
4.文件指纹
- [name].[hash].[chunkhash][contenthash]
- index.a3bd99789df37566168d.71c15242d8b46a83a236.2e8fcc1d5f3161e8265a
- hash: 代码一次编译 不管改多少文件 每次编译都会产生同一个新的hash 资源的hash都是相同的
- chunkHash: 同一个入口生成的chunkHash都是相同的
- contentHash: 内容hash 根据内容计算得到的 文件内容不变 不管多少次编译 生成的contentHash都一样
- name: 代码块的名称 entry中的key
5. 有哪些常见的优化策略
- 使用分析插件 webpack-bundle-analyzer speed-measure-webpack-plugin生成分析报告 定位问题
- 升级node版本 往往这样很有用
- 搜小查找的范围 exclude noParse(指定不需要解析的模块文件) extensions alias
// 缩小查找范围 减少查找时间
resolve: {
extensions: ['.js', '.jsx', '.json', '.css'], // 后缀
alias: {'@': 'src', // 别名 },
},
module: {
// 不解析 用来配置那些模块不需要解析
// noParse: 'jquery|lodash',// noParse: /jquery|lodash/, // 正则表达式
// 忽略的文件中不应该含有 import, require, define 的调用 不解析就是没有导入其他的文件
// 解析的时候变成一个语法树 分析import和require找到依赖性递归解析 提高编译速度
noParse(moduleName) { // 很少使用 一般库中都有依赖的
return /jquery|lodash/.test(moduleName);
},
// 配置转换的规则
rules: [{
test: /\.js(x)?$/,
loader: 'eslint-loader',
enforce: 'pre', // pre post normal
include: path.resolve(__dirname, 'src'),
exclude: /node_modules/, // 排除
options: { fix: true, }, // 自动修复
},
}
- 代码压缩 充分利用缓存 babel-loader cache-loader hard-source-webpack-plugin(有时更新会有问题)
- cdn 并行加载不阻塞
- 将不同的静态资源分配到不同的cdn服务器上
- 静态的js css 图片等文件开启cdn和缓存 文件名带上hash值
- html文件不缓存 放在自己的服务器上 关闭自己服务器的缓存 静态资源的url变成cdn服务地址
- 预获取
<link ref="dns-prefetch" href="//tce.taobao.com">
- dll动态链接库 开发阶段最有效的方式
- webpack.dll.config.js 生成动态链接库
- new DllReferencePlugin() 使用
- 代码分隔 生产环境非常有用的优化手段
- 基础类库 方便长期缓存
- 页面之间公共代码
- 按需加载等
// 在optimization中配置
splitChunks: {
chunks: 'all', // 默认作用域异步chunk 值为all initial async
minSize: 30 * 1000, // 默认一个模块的最小大小是30k 大于30k的单独打包
minChunks: 2, // 被引用多少次被分隔
maxAsyncRequests: 5, // 按需加载的最大异步并行请求数 import()
maxInitialRequests: 3, // 一个入口文件最大并行请求数
name: true, // 打包后的代码块需要一个名称 默认是chunk的名字通过分隔符(~)分开
automaticNameDelimiter: '~', // 名称分隔符
cacheGroups: { // 设置缓存组用来抽取满足不同规则的chunk
vendors: {
chunks: 'initial',
name: 'vendors', // 切割之后代码块的名字
test: /node_modules/, // 哪些模块放到vendors代码块中
priority: 10, // 优先级 默认值为0
},
commons: {
chunks: 'initial',
name: 'commons',
minSize: 0, // 最小剔除模块
minChunks: 2, // 最少被引用几次
priority: 20,
reuseExistingChunk: true // 如果该chunk引用了已经被抽取的chunk直接引用
}
}
},
- 代码压缩 css压缩 多进程(thread-loader) tree shaking 作用域提升等webpack都内置了
optimization: {
// minimizer最小化 压缩
minimizer: argv.env == 'production' ? [
new TerserWebpackPlugin({ // 压缩js
parallel: true, // 开启多进程并行压缩 happypack开启子线程 没必要
cache: true, // 开启缓存
}),
new OptimizeCssAssetsWebpackPlugin({}), // 压缩css
] : [],
},
- 动态导入 懒加载 import()语法 webpack会查找import语法 单独打包
- 预加载和预拉取 preload prefetch (element中会删掉这两个 影响了懒加载)
6. 多入口打包处理
7. 简述webpack的构建流程
- 初始化参数得到options const options = require('./webpack.config.js')
- 执行webpack(options)得到compiler 执行一系列的插件
- 执行compiler.run()方法开始编译
- 生成compilation对象 new Compilation(params) 执行make开始真正的编译
- compilation addEntry()增加入口 从入口开始(单入口插件)调用普通的模块工厂开始编译
- addModuleChain() 编译的入口 添加模块依赖链 拿到模块工厂创建模块
- 拿到解析器resolver解析模块和loader 找到模块和loader的绝对路径(加强的node文件查找)
- resolve之后 执行run-loader 解析模块内容
- 创建模块createModule() 构建module会执行loader-runner
- build分析文件内容 通过ast语法解析 递归处理 得到依赖项和异步依赖项
- 递归处理依赖项
- seal封装 生成chunk
- 生成模块依赖图 在生成chunk group 进行优化得到chunk
- 生成资源 遍历chunks使用不同的模块生成代码 (简单理解为不同的ejs模板文件 lazy chunkTemplate mainTemplate)
- 写入到文件系统中
const webpack = require('webpack')
const options = require('./webpack.config.js')
debugger
// webpack就是一个函数 返回编译对象
const compiler = webpack(options)
// stats编译的结果信息 compilation.getStats() modules解析的模块 chunks所有的chunk assets生成的文件
// npx webpack --profile --json > stats.json
compiler.run((err, stats) => { console.log('done')})
8. 简述loader的分类和执行流程
9. 如何实现自定义的loader
10. 插件是如何实现的
11. 实现按需导入插件
12. 简述webpack热更新原理
13. react和vue配置 常见vue.config.js配置
14. 简单谈谈ast
15. 生成环境如何使用sourcemap 如何调试代码
- source-map eval-source-map cheap-module-eval-source-map cheap-eval-source-map eval
- eval(使用eval包裹代码 有最好的性能) source-map(产生.map文件) cheap(不包含列信息) module(包含loader 否则无法定位源文件) inline(不生成.map文件作为dataurl嵌入)
- sourcemap原理?
- 开发环境需要块eval和信息全module 推荐配置devtool: cheap-module-eval-source-map
- 生产环境我们不需要别人可以看到源代码 不直接提供sourcemap给浏览器
- 但是我们需要sourcemap定位错误信息 设置hidden-source-map(会生成但是不会映射)
- 将map文件放到本地服务器 将不包含map文件部署到服务器 借助第三方软件fiddler将浏览器map文件请求拦截到本地服务器可以实现本地sourcemap调试
- 一些监控平台支持上传sourcemap文件(sentry)
16. webpack5有哪些新特性和优化
17. 打包生成文件分析
发表评论
还没有评论,快来抢沙发吧!