网站建设费用表,百度小说搜索风云榜总榜,天通苑网站建设,关于网站建设的图片1.说说你对webpack的理解
开发时#xff0c;我们会使用框架 (React、Vue) #xff0c;ES6 模块化语法#xff0c;Less/Sass 等 CSS 预处理器等语法进行开发#xff0c;这样的代码要想在浏览器运行必须经过编译成浏览器能识别的 JS、CSS语法才能运行。所以我们需要打包工…1.说说你对webpack的理解
开发时我们会使用框架 (React、Vue) ES6 模块化语法Less/Sass 等 CSS 预处理器等语法进行开发这样的代码要想在浏览器运行必须经过编译成浏览器能识别的 JS、CSS语法才能运行。所以我们需要打包工具帮我们做完这些事。除此之外打包还能压缩代码、做兼容性处理、提升代码性能等。 webpack 是一个静态模块的打包工具。它会在内部从一个或多个入口点构建一个依赖图然后将项目中所需的每一个模块组合成一个或多个 bundles 进行输出它们均为静态资源。输出的文件已经编译好了可以在浏览器运行。 webpack 具有打包压缩、编译兼容、能力扩展等功能。其最初的目标是实现前端项目的模块化也就是如何更高效地管理和维护项目中的每一个资源。
2.说说webpack的构建流程
初始化参数从配置文件和 Shell 语句中读取与合并参数得出最终的参数
开始编译用上一步得到的参数初始化 Compiler 对象加载所有配置的插件执行对象的 run 方法开始执行编译
确定入口根据配置中的 entry 找出所有的入口文件
编译模块从入口文件出发调用所有配置的 Loader 对模块进行翻译再找出该模块依赖的模块再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理
完成模块编译在经过第4步使用 Loader 翻译完所有模块后得到了每个模块被翻译后的最终内容以及它们之间的依赖关系
输出资源根据入口和模块之间的依赖关系组装成一个个包含多个模块的 Chunk再把每个 Chunk 转换成一个单独的文件加入到输出列表
输出完成在确定好输出内容后根据配置确定输出的路径和文件名把文件内容写入到文件系统
在以上过程中webpack会在特定的时间点广播出特定的事件插件在监听到事件后会执行特定的逻辑并且插件可以调用webpack提供的API改变webpack的运行结果
3.Loader是什么
其作用是让 Webpack 能够去处理那些非 JavaScript 文件。由于 Webpack 自身只理解 JavaScript、JSON 其他类型/后缀的文件都需要经过 loader 处理并将它们转换为有效模块。loader 可以是同步的也可以是异步的而且支持链式调用链中的每个 loader 会处理之前已处理过的资源。 loader的两个属性 1.test识别出哪些文件会被转换 2.use在进行转换时使用的loader 多loader的执行顺序从右到左从下到上
4.常用的Loader
babel-loader 将ES6代码转换成ES5版本
ts-loader ts转js 如果没有babel使用ts-loader有babel用babel/preset-typescript
sass-loader sass转换css
style-loader 创建
css-loader 将css转为js模块导出
url-loader url-loader可以在图片大小小于设定的limit的时候返回的是base编码的图片大于limit时会调用file-loader对图片进行处理。
file-loader 其实就是将文件拷贝到输出目录下使用file-loader中配置的新名字
postcss-loader 1将css解析成js可以操作的AST2调用插件来处理AST并得到结果。
经常配合autoprefixer自动为CSS添加浏览器前缀
html-loader 将html代码转换为js模块导出
eslint-loader 检查代码是否符合eslint规范只检查错误不修改代码
5.手写Loader
const loaderUtils require(loader-utils);module.exports function(source){// 知识点一 如果为每个构建执行重复的转换操作这样webpack的构建可能会变得非常慢// 开启缓存this.cacheable this.cacheable();// 知识点二 使用loaderUtils 获取loader的参数const options loaderUtils.getOptions(this);console.log(options -, options);// 知识点三 告诉 Webpack 本次转换是异步的Loader 会在 callback 中回调结果 // 异步用this.axync() 同步用this.callback()var callback this.async() // someAsyncOperation 代表一些异步的方法someAsyncOperation(source).then(res {// 通过 callback 返回异步执行后的结果callback(err, result, sourceMaps, ast)})// 真正的手写代码const reg /(console.log((.*)))/g;source source.replace(reg, );this.callback(null, source);// return undefined的作用是让webpack知道loader返回的结果应该在this.callback当中而不是return中return;
}/**
this.callback( // 当无法转换原内容时给 Webpack 返回一个 Error err: Error | null, // 原内容转换后的内容 content: string | Buffer, // 用于把转换后的内容得出原内容的 Source Map方便调试sourceMap?: SourceMap, // 如果本次转换为原内容生成了 AST 语法树可以把这个 AST 返回,以方便之后需要 AST 的 Loader 复用该 AST以避免重复生成 AST提升性能 abstractSyntaxTree?: AST
);
*/6.Plugins是什么
由于webpack基于发布订阅模式在运行的生命周期中会广播出许多事件插件通过监听这些事件就可以在特定的时机执行自己的插件任务webpack有两个核心对象
compiler包含了 webpack 环境的所有的配置信息包括 optionsloader 和 plugin和 webpack 整个生命周期相关的钩子
compilation作为 plugin 内置事件回调函数的参数包含了当前的模块资源、编译生成资源、变化的文件以及被跟踪依赖的状态信息。当检测到一个文件变化一次新的 Compilation 将被创建
1.插件必须是一个带有apply方法的对象
2.不建议修改compiler和compilation对象因为传入的同一个对象的引用
class CopyrightWebpackPlugin {// 编写一个构造器// 参数初始化constructor(options) {console.log(options)}apply(compiler) {//遇到同步时刻 同步用tapcompiler.hooks.compile.tap(CopyrightWebpackPlugin,() {console.log(compiler);});//遇到异步时刻 异步用tapAsync// emit 输出asset到output目录之前执行//Compilation存放打包的所有内容Compilation.assets放置生成的内容compiler.hooks.emit.tapAsync(CopyrightWebpackPlugin, (Compilation, callback) {debugger;// 往代码中增加一个文件copyright.txtCompilation.assets[copyright.txt] {source: function() {return copyright by monday;},size: function() {return 19;}};callback();})}
}module.exports CopyrightWebpackPlugin;7.常用的Plugin
1.HtmlWebpackPlugin
2.CleanWebpackPlugin
3.CopyWebpackPlugin
4.Webpack.DefinePlugin 定义全局变量
5.MiniCssExtractPlugin 将css抽取成单独的文件
6.PurgeCSSPlugin 删除没用到的CSS样式需要判断引用文件起到css tree-shaking的效果
7.webpack.ProvidePlugin 配置全局模块避免多次引入的麻烦
8.BundleAnalyzerPlugin 分析打包后资源的依赖以及大小
9.ImageminPlugin 压缩图片
10.CompressionPlugin 启用传输压缩gzip压缩需要服务端配合
11.webpack.NoEmitOnErrorsPlugin 遇到编译报错不输出
12.OptimizeCssAssetsPlugin 压缩css去除重复的类名样式去除无用的空格
13.UglifyJSPlugin 压缩JS
14.webpack.HotModuleReplacementPlugin 热更新插件
15.TerserPlugin 压缩es6相比UglifyJsPlugin插件能更好的处理ES6以上的语法
8.实现一个Plugin
由于webpack基于发布订阅模式在运行的生命周期中会广播出许多事件插件通过监听这些事件就可以在特定的时机执行自己的插件任务webpack有两个核心对象
compiler包含了 webpack 环境的所有的配置信息包括 optionsloader 和 plugin和 webpack 整个生命周期相关的钩子
compilation作为 plugin 内置事件回调函数的参数包含了当前的模块资源、编译生成资源、变化的文件以及被跟踪依赖的状态信息。当检测到一个文件变化一次新的 Compilation 将被创建
在这里插入代码片class CopyrightWebpackPlugin {// 编写一个构造器// 参数初始化constructor(options) {console.log(options)}apply(compiler) {//遇到同步时刻 同步用tapcompiler.hooks.compile.tap(CopyrightWebpackPlugin,() {console.log(compiler);});//遇到异步时刻 异步用tapAsync// emit 输出asset到output目录之前执行//Compilation存放打包的所有内容Compilation.assets放置生成的内容compiler.hooks.emit.tapAsync(CopyrightWebpackPlugin, (Compilation, callback) {debugger;// 往代码中增加一个文件copyright.txtCompilation.assets[copyright.txt] {source: function() {return copyright by monday;},size: function() {return 19;}};callback();})}
}module.exports CopyrightWebpackPlugin;9.Source map是什么
source map是将编译、打包、压缩后的代码映射和回源代码的过程。打包压缩后的代码不具备良好的可读性想要调试代码就需要source-map提高开发效率
10.文件指纹是什么
文件指纹是打包文件的唯一标识文件指纹通常有两个用途 版本管理 在发布版本时通过文件指纹来区分 修改的文件 和 未修改的文件。 使用缓存 未修改的文件文件指纹保持不变浏览器继续使用缓存访问。 Hash 是和整个项目的构建相关compilation 实例的变化就会触发 Hash 的变化。 Chunkhash 是和 webpack 打包的模块相关每一个 entry 作为一个模块会产生不同的 Chunkhash 值所以他们之间的变化是互不影响的。 Contenthash 是和根据文件内容相关比如一个页面内的 JS 内容、CSS 内容都会拥有自己的 Contenthash可以保持各自的独立更新。
11.说说webpack热更新的原理
HMR全称Hot Module Replacement可以理解为模块热替换指在应用程序运行过程中替换添加删除模块而无需重新刷新整个应用。 例如我们在应用运行过程中修改了某个模块通过自动刷新会导致整个应用的整体刷新那页面中的状态信息都会丢失如果使用的是 HMR就可以实现只将修改的模块实时替换至应用中不必完全刷新整个应用 webpack的原理 启动阶段 1-2-A-B 在编写为经webpack打包的源代码后webpacl compiler将源代码和HMR Runtime一起编译成bundle文件放在webpack Dev Server当浏览器请求bundle.js文件时bundle.js就返回给浏览器运行在浏览器上 socket.js在服务器和浏览器建立了一个websocket长链接 更新阶段 1-2-3-4 当某一个文件或者模块发生变化时webpack监听到文件变化对文件重新编译打包编译生成唯一的hash值本次生成的hash值会作为下一次热更新的标识也就是本次热更新使用的hash值是上一次热更新生成文件的hash此次的hash值是上次热更新中manifest中h的值 由于socket服务器在HMR Runtime 和 HMR Server之间建立 websocket链接当文件发生改动的时候服务端会向浏览器推送一条消息消息包含文件改动后生成的hash值如下图的h属性作为下一次热更细的标识 浏览器根据hash标识去创建ajax去获取此次的mainfest(hbuild生成的hash值c变化的模块 )文件使用jsonp获取此次的修改内容浏览器拿到这两个文件后通过HMR runtime机制加载这两个文件触发render流程实现局部刷新
12.说说webpack proxy工作原理
在开发阶段 webpack-dev-server 会启动一个本地开发服务器所以我们的应用在开发阶段是独立运行在 localhost的一个端口上而后端服务又是运行在另外一个地址上
所以在开发阶段中由于浏览器同源策略的原因当本地访问后端就会出现跨域请求的问题
通过设置webpack proxy实现代理请求后相当于浏览器与服务端中添加一个代理者
当本地发送请求的时候代理服务器响应该请求并将请求转发到目标服务器目标服务器响应数据后再将数据返回给代理服务器最终再由代理服务器将数据响应给本地 在代理服务器传递数据给本地浏览器的过程中两者同源并不存在跨域行为这时候浏览器就能正常接收数据
注意服务器与服务器之间请求数据并不会存在跨域行为跨域行为是浏览器安全策略限制
13.webpack打包体积优化
一、提取公共模块
假如现在有一个MPA多页面应用的react项目每个页面的入口文件及其依赖的组件中都会引入一份react和react-dom等那最终打包后的每个页面中同样也会有一份以上的公共包的代码可以将这个包单独抽离出来最终在每个打包后的页面入口文件引入从而减少打包后的总体积
module.exports {optimization: {splitChunks: {minSize: 20000,cacheGroups: {react: {test: /(react|react-dom)/,name: vendors,chunks: all,},},},}
};二、配置CDN服务器
1.可以修改output{publicPath: ‘’} 的值打包时添加上自己的CDN地址
2.在CDN上部署自己依赖的第三方资源
3.在externals中加入不进行打包的资源在html模版中加入CDN服务器地址 4.如果没有自己配置CDN服务器可以使用其他人放置在cdn服务器上的资源
三、代码压缩此处的代码压缩并非真正的压缩而是删掉代码中无意义的部分例如空格
1.压缩js使用插件TerserPlugin 2.压缩css使用CSSMinimizerPlugin
css压缩通常是去除无用的空格等因为很难去修改选择器属性和名称、值等 3.压缩html使用HtmlWebpackPlugin的minify配置
new HtmlWebpackPlugin({template: path.join(__dirname, ./public/index.html),filename: index.html,minify: { // minify配置可以压缩html文件设置了minify实际上会使用另一个插件html-minifier-terserminifyCSS: false, //是否压缩csscollapseWhitespace: true, // 是否折叠空格removeComments: true, // 是否移除注释}
}),4.压缩图片使用image-webpack-loader
这个不太理解压缩后图片会不会失真或者像素变低打包的时候压缩使用的时候进行解压缩
四、使用TreeShaking
tree shaking是一个术语在计算机中标识消除死代码尽量使用纯函数编程用于消除未调用的代码
1.JS实现Tree Shaking
1usedExports配置方法很简单只需将usedExports设置为true
module.exports {...optimization:{usedExports}
}使用后没被用上的代码在webpack打包中会添加 unused harmony export … 注释用来告知Terser在优化时可以删掉这段代码 2sideEffects实现
sideEffects用于指定哪些模块是有副作用的副作用指的是这里面的代码有执行一些特殊的任务不能仅仅依靠export来判断这段代码的意义
sideEffect设置为false就是告知webpack可以安全的删除未用到的exports
sideEffect设置为数组则将代码中的数据进行保留 总结
在optimization中配置usedExports为true来帮助Terser进行优化在package.json中配置sideEffects直接对模块进行优化
2.CSS实现Tree Shaking
css主要使用的purgecss-webpack-plugin 五、文件大小压缩真正意义的压缩gzip算法
compression-webpack-plugin 插件
对文件的大小进行压缩将前端打包好的资源文件进一步压缩生成指定的、体积更小的压缩文件减小http传输过程中带宽的损耗
new ComepressionPlugin({test:/\.(css|js)$/, // 哪些文件需要压缩threshold:500, // 设置文件多大开始压缩minRatio:0.7, // 至少压缩的比例algorithm:gzip, // 采用的压缩算法
}) 使用npm run build会生成许多以.gz格式的文件 生成压缩后的文件不能直接使用需要服务端配置才可以使用而且发现打包生成的“dist/index.html”首页内也没有直接引用这些“.gz”格式的文件。 而实现的关键其实就是让服务端向浏览器发送“Content-Encodinggzip”这个响应头并把对应的“.gz”格式文件发送给浏览器让浏览器通过“gzip”编码格式来解析资源。
const path require(path);
const fs require(fs);
const express require(express);
const app express();app.use((request, response, next) {const fullPath path.join(__dirname, ${request.originalUrl}.gz); // 检测是否存在同名.gz压缩文件if (fs.existsSync(fullPath)) {// 存在就告诉浏览器用gzip编码格式来解析并把对应的“.gz”格式文件发送给浏览器。response.setHeader(Content-Encoding, gzip) response.sendFile(fullPath);} else {next()}
})
app.use(express.static(./));app.listen(1055, _ {console.log(1055服务器已经启动);
});六、antd按需导入
import {Col,Row} from antd14.优化构建速度
这个问题个人认为比较宽泛顺着聊几点就好了答不上来也没关系重点是上面的压缩打包后的体积
可以使用speed-measure-webpack-plugin统计总打包耗时以及每个plugin和loader的打包耗时
一、缩小构建范围、优化Loader配置
在使用loader时可通过配置include、exclude、test属性来匹配文件
module.exports {module: {rules: [{// 如果项目源码中只有 js 文件就不要写成 /\.jsx?$/提升正则表达式性能test: /\.js$/,// babel-loader 支持缓存转换出的结果通过 cacheDirectory 选项开启use: [babel-loader?cacheDirectory],// 只对项目根目录下的 src 目录中的文件采用 babel-loaderinclude: path.resolve(__dirname, src),},]},
};二、优化resolve.alias
alias给一些常用的路径起一个别名特别当我们的项目目录结构比较深的时候一个文件的路径可能是./../../的形式
通过配置alias以减少查找过程
module.exports {...resolve:{alias:{:path.resolve(__dirname,./src)}}
}三、多进程构建
对于耗时较长的模块同时开启多个 nodejs 进程进行构建可以有效地提升打包的速度。terser启动多线程
module.exports {optimization: {minimizer: [new TerserPlugin({parallel: true,}),],},
};四、合理使用source-map
打包生成sourceMap的时候信息越详细打包速度就越慢
五、cache-loader
在一些性能开销较大的 loader之前添加 cache-loader以将结果缓存到磁盘里显著提升二次构建速度
保存和读取这些缓存文件会有一些时间开销所以请只对性能开销较大的 loader 使用此loader
module.exports {module: {rules: [{test: /\.ext$/,use: [cache-loader, ...loaders],include: path.resolve(src),},],},
};