学习】对工程化、wepack的理解
前端的理解
浏览器会识别解析渲染html、css、js等生成页面,而一些比较新的html、css、js的api和vue、less、sass等浏览器是无法识别的,所以就需要用到webpack、gulp、grunt、vite、rollup、rolldown等工具解析转成浏览器能识别的语言渲染成页面。
webpack
webpack解析的几个流程
1.输入 --> 2.生成模块依赖并解析(代码分割、模块合并、TreeShaing、压缩等优化策略) --> 3.输出
输入
1.SPA应用通常只有一个输入文件
2.MPA应用有多个输入文件
entry: {
"entry.page1": "./app/pages/page1/entry.page1.js",
"entry.page2": "./app/pages/page2/entry.page2.js",
},
生成模块依赖并解析(代码分割、模块合并、TreeShaing、压缩等优化策略)
由于webpack只能识别js,收集模块依赖时,会有多种不同的文件后缀和路径查找,便于开发者开发,可以直接配置自动添加后缀名和配置别名进行依赖收集。
extensions: [".js", ".vue", ".less", ".css"],
alias: {
$pages: path.resolve(process.cwd(), "./app/pages"),
$common: path.resolve(process.cwd(), "./app/pages/common"),
$widgets: path.resolve(process.cwd(), "./app/pages/widgets"),
$store: path.resolve(process.cwd(), "./app/pages/store"),
解析时对于哪些非js的编码webpack无法识别,而webpack loader是可以将编码转成js,我们可以自己编写一个loader将指定文件转成js,也可以使用第三方库。
rules: [
{
test: /\.vue$/,
use: {
loader: "vue-loader",
},
},
{
test: /\.js$/,
// 只对业务代码进行 babel, 加快 webpack 打包速度
include: [path.resolve(process.cwd(), "./app/pages")],
use: {
loader: "babel-loader",
},
},
{
test: /\.(png | jpe?g| gif)(\?.+)?$/,
use: {
loader: "url-loader",
options: {
limit: 300,
esModule: false,
},
},
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.(eot | svg | ttf | woff| woff2)(\?\S*)?$/,
use: "file-loader",
},
],
webpack plugin可以在解析webpack的某个生命周期中添加一些全局变量或是一些功能。
// 处理 .vue 文件
// 它是将你定义过的其他规则复制并应用到.vue 文件里
// 例如: 如果有一天匹配规则 /\.js$/ 的规则,那么它会应用到 .vue 文件中的 <script>模块中
new VueLoaderPlugin(),
// 把第三库暴露到 window context下
new webpack.ProvidePlugin({
Vue: "vue",
axios: "axios",
_: "lodash",
}),
// 定义全局变量
new webpack.DefinePlugin({
__VUE_OPTIONS_API__: true, // 支出 vue 解析 optionApi
__VUE_PROD_DEVTOOLS: false, // 禁用 vue 调试工具
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false, // 禁用生产环境显示 "水合" 信息
}),
// 构建最终渲染的页面模版
new HtmlWebpackPlugin({
//产物(最终模版) 输出路径
filename: path.resolve(
process.cwd(),
"./app/public/dist/",
"entry.page1.tpl"
),
// 指定要使用模版文件
template: path.resolve(process.cwd(), "./app/view/entry.tpl"),
// 要注入的代码块
chunks: ["entry.page1"],
}),
打包优化,对于稳定的第三包和业务的公共编码,常规编码,以及webpack运行时注入的编码进行分包,利用浏览器的缓存做优化
/**
* 把js 文件打包成3种类型
* 1.vendor:第三方 lib库 ,基本不会变动,除非依赖升级
* 2.common:业务组件代码的公共部分抽取出来,改动比较少
* 3.entry.{page}: 不同页面 entry 里的业务组件代码的差异部分,会经常改动
* 目的:把改动和引用频率不一样的 js 区分出来,以达到更好的浏览器缓存的效果
*/
splitChunks: {
chunks: "all", // 对同步和异步模块都进行分割
maxAsyncRequests: 10, //每次异步加载的最大并行请求数
maxInitialRequests: 10, //入口点的最大并行请求数
cacheGroups: {
// 第三方依赖库
vendor: {
test: /[\\/]node_modules[\\/]/, //匹配打包 node_modules 文件
name: "vendor", //模块名称
priority: 20, //优先级,数字越大,优先级越高
enforce: true, // 强制执行
reuseExistingChunk: true, //复用已有的公共 chunk
},
//公共模块
common: {
name: "common", //模块名称
minChunks: 2, // 被两处引用即被视为公共模块
minSize: 1, //最小分割文件大小 (1byte)
priority: 10, //优先级
reuseExistingChunk: true, //复用已有的公共 chunk
},
},
},
// 将webpack 运行时生成的代码打包到 runtime.js
runtimeChunk: true,
输出
解析压缩完成生成hash输出到指定的文件目录下
filename: "js/[name]_[chunkhash:5].bundle.js",
path: path.join(process.cwd(), "./app/public/dist/prod"),
publicPath: "/dist/prod",
crossOriginLoading: "anonymous",
总结
页面需要的html、css、js,使用vue写页面是便于前端模块开发维护,就需要一个工具将vue里的编码转成页面需要的语言。前端工具有很多webpack、gulp、grunt、vite、rollup、rolldown等。
更多前端面试资料:前端资料