大厂面试题分享 面试题库
前后端面试题库 (面试必备) 推荐:★★★★★
地址:前端面试题库 web前端面试题库 VS java后端面试题库大全
前端开发是一个快速发展的领域,每天都会涌现出新的技术和工具。在实现功能的同时,开发人员面临着许多挑战如代码可维护性,加载时间,访问速度,构建速度等问题。这些挑战可能直接影响网站的性能和用户体验,需要采取一些优化措施来改善问题。在本文中,我们将探讨一些前端项目优化的具体措施,旨在帮助开发人员提高项目效率,升级用户体验。
综合各方面来说 就是小, 少, 快
小:减少项目体积
使用模块化开发,禁止使用全局变量和函数,尽量减少污染全局变量;
合理使用 Tree Shaking 和 Dead Code Elimination,只打包使用到的代码;
对于静态资源,尽量使用 CDN 加载外部资源,减轻服务器负担;
使用 Code splitting 减小入口文件的大小,按需加载组件和路由;
对于需要在不同页面中间切换的模块可以考虑使用 Vue 的 keep-alive 缓存机制。
少:减少 HTTP 请求次数
首先明确必须要的请求,其余的请求可以通过 Vue 的异步组件按需加载;
将常用的图片、Logo、Icon 等打包到 CSS 文件中,减小图片请求次数;
对于 AJAX 请求,可以采用缓存和数据请求合并等优化方式,减少请求次数。
快:提高页面加载速度
对于 Vue 项目,使用 Vue-Router 实现路由懒加载、动态加载,以及异步组件等方式;
对于静态资源,如图片、CSS、JS 等文件,使用 Gzip 或者 Brotli 等方式进行压缩,减小文件大小;
合理使用缓存,如 CDN 缓存、浏览器缓存等;
对于 Vue 页面,采用服务端渲染(SSR)可以提高首屏渲染速度;
对于代码压缩、合并等优化,现代构建具如 Vue CLI 已经集成了很好的优化策略;
量化工具
在进行项目优化的时候,不能盲目的从网上或者其他文档上找优化配置进行添加,你需要对项目的实际情况进行一个了解, 才能对症下药, 比如你需要知道打包耗了多长时间,具体哪个loderl或者plugin耗时长,打包资源各个模块的体积等等.
所以在开始优化之前,需要安装一些插件,帮助我们分析
progress-bar-webpack-plugin
查看编译进度
// 安装 npm i -D progress-bar-webpack-plugin // 使用 const chalk = require('chalk') const ProgressBarPlugin = require('progress-bar-webpack-plugin') module.exports = { plugins: [ // 进度条 new ProgressBarPlugin({ format: ` :msg [:bar] ${chalk.green.bold(':percent')} (:elapsed s)` }) ], } // 包含内容、进度条、进度百分比、消耗时间,进度条
speed-measure-webpack-plugin
编译速度分析
这个插件可以我们知道哪些plugin,哪些loader所耗时长,以及总打包编译时长, 帮助我们针对性的优化
// 安装 npm i -D speed-measure-webpack-plugin // 配置方式一, 如果你是webpack搭建的项目, const SpeedMeasurePlugin = require("speed-measure-webpack-plugin"); const smp = new SpeedMeasurePlugin(); module.exports = smp.wrap({ // ...webpack config... }) // 如果你是vuecli搭建的项目, 则如下 const SpeedMeasureWebpackPlugin = require('speed-measure-webpack-plugin') module.exports = { chainWebpack: config => { config.plugin('speed') .use(SpeedMeasureWebpackPlugin) } }
效果如下
webpack-bundle-analyzer
打包体积优化
这个插件可以让我们看到打包后的资源之中每个模块的大小``
// 安装 npm i -D webpack-bundle-analyzer // 使用 如果是webpack搭建的项目 // webpack.prod.js const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; module.exports = { plugins: [ // 打包体积分析 new BundleAnalyzerPlugin() ], } **// 如果是vuecli 则无需安装 已经内部安装了** 直接使用 npm run build --report 命令 或者 npm run build -- --report 就会在打包目录下生成一个report.html文件,打开这个文件就知道了
配置指南
任何优化,都要对症下药,而不是盲目的从网上找配置一股脑地堆上去, 比如说启动慢,构建慢,则可以用下面提到的缓存和多核多进程相关的配置进行提升, 优化打包资源则需要要具体分析,如下图,这个是一个项目里面的打包资源分析(通过webpack-bundle-analyzer
生成),可以清晰的知道生成打包资源各个模块的大小,进而针对性的优化.
打包生成的资源大小
开启压缩后,gizp资源的大小
使用缓存能力
增加对应的缓存配置, 可以很好的提升构建和启动速度, 尤其是多次构建和启动(或热更新)的场景
cache-loader
与cache
配置
在webpack搭建的项目中,可以使用上述两个东西,改善构建速度
但是在vuecli创建的项目则不用
VueCli
自带
cache-loader 会默认为 Vue/Babel/TypeScript
编译开启。文件会缓存在 node_modules/.cache
中。 如果你遇到了编译方面的问题,记得先清缓存目录之后再试试看。
thread-loader 会在多核 CPU 的机器上为 Babel/TypeScript
转译开启。
hard-source-webpack-plugin
这个插件主要是利用缓存,提升二次启动和二次打包的速度, 效果很直观
使用方式
// vue.config.js 在vuecli中 const HardSourcePlugin = require('hard-source-webpack-plugin') module.exports = { configureWebpack: { plugins: [new HardSourcePlugin()] } } // webpack.config.js 在webpack搭建的项目中 const HardSourcePlugin = require('hard-source-webpack-plugin') module.exports = { mode: 'development', ... plugins: [new HardSourcePlugin()] }
开启babel缓存
只需要在babel-loader
的配置里加一个参数即可:cacheDirectory: true
{ test: /.js$/, exclude: /node_modules/, loader: 'babel-loader', options: { presets: [ [ '@babel/preset-env', { useBuiltIns: 'usage', corejs: { version: 3 }, targets: { chrome: '60', firefox: '50' } } ] ], // 开启babel缓存 // 第二次构建时,会读取之前的缓存 cacheDirectory: true } },
生成gizp的打包资源
打包的时候开启gzip可以很大程度减少包的大小,页面大小可以变为原来的30%甚至更小,非常适合线上部署, 但还记得需要服务端支持
compression-webpack-plugin
前端配置
]// vue.config.js 在vuecli中 /* 第一种方式 */ const CompressionWebpackPlugin = require('compression-webpack-plugin') const plugins = [...] if (isProduction) { plugins.push( new CompressionWebpackPlugin({ filename: '[path].gz[query]', algorithm: 'gzip', test: new RegExp('\.(' + ['html', 'js', 'css'].join('|') + ')$'), threshold: 10240, // 只有大小大于该值的资源会被处理 10240 minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理 deleteOriginalAssets: false // 删除原文件 }) ) } module.exports = { configureWebpack: { resolve: { alias: { '@': resolve('./src') } }, plugins }, } /* 第二种方式 在vuecli中*/ // configureWebpack 返回函数式写法 const CompressionWebpackPlugin = require('compression-webpack-plugin') const isProduction = process.env.NODE_ENV !== 'development' module.exports = { ... configureWebpack: (config) => { config.plugins.push( new HardSourcePlugin() ) // 其他配置 Object.assign(config.resolve, { alias: { '@': resolve('./src') } }) // 为生产环境修改配置 if (isProduction) { config.plugins.push( new CompressionWebpackPlugin({ filename: '[path].gz[query]', algorithm: 'gzip', test: new RegExp('\.(' + ['html', 'js', 'css'].join('|') + ')$'), threshold: 10240, // 只有大小大于该值的资源会被处理 10240 minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理 deleteOriginalAssets: false // 删除原文件 }) ) } }, } // webpack.config.js 在webpack搭建的项目中 const CompressionWebpackPlugin = require('compression-webpack-plugin') module.exports = { mode: 'development', ... plugins: [ new CompressionWebpackPlugin({ filename: '[path].gz[query]', algorithm: 'gzip', test: new RegExp('\.(' + ['html', 'js', 'css'].join('|') + ')$'), threshold: 10240, // 只有大小大于该值的资源会被处理 10240 minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理 deleteOriginalAssets: false // 删除原文件 }) ]
服务端配置, 以nginx为例
服务端 Nginx 需开启 gzip_static 功能;
在nginx.conf的server模块中加入以下代码:
server{ //开启和关闭gzip模式 gzip on; //gizp压缩起点,文件大于2k才进行压缩;设置允许压缩的页面最小字节数,页面字节数从header头得content-length中进行获取。 默认值是0,不管页面多大都压缩。建议设置成大于2k的字节数,小于2k可能会越压越大。 gzip_min_length 2k; // 设置压缩所需要的缓冲区大小,以4k为单位,如果文件为7k则申请2*4k的缓冲区 gzip_buffers 4 16k; // 设置gzip压缩针对的HTTP协议版本 gzip_http_version 1.0; // gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间 gzip_comp_level 2; //进行压缩的文件类型 gzip_types text/plain application/javascript text/css application/xml; // 是否在http header中添加Vary: Accept-Encoding,建议开启 gzip_vary on; }
访问时 可以看到
利用多核/多进程能力
thread-loader
多进程程处理loader
使用时,需将此 loader 放置在其他 loader 之前。放置在此 loader 之后的 loader 会在一个独立的 worker 池中运行。
本身启动进程就需要耗费时间,**请仅在耗时的操作中使用此 loader!**要不然收益达不到你的预期
happypack
启动多进程来优化构建速度,但是作者不维护了,注意安装版本,
替换方案建议使用thread-loader
{ // 当js代码用babel处理兼容性且本身代码就比较多的情况下可以使用thread-loader开启多线程打包 // thread-loader本身启动进程就需要耗费时间, 所以当js代码不多时就不要开启, 否则还可能会延长打包时间 test: '/.js$/', exclude: /node_modules/, use: [ { loader: 'thread-loader', options: { // 默认是cpu核 - 1, 可以通过这里更改开启几个进程 works: 2 } } ] }
// @file: webpack.config.js const HappyPack = require('happypack'); var happyThreadPool = HappyPack.ThreadPool({ size: 5 }); exports.module = { rules: [ { test: /.js$/, // 1) replace your original list of loaders with "happypack/loader": // loaders: [ 'babel-loader?presets[]=es2015' ], use: ['happypack/loader'?id=babel], // 这里的id 就是定义在plugin里面HappyPack实例构造参数传入的id include: [ /* ... */ ], exclude: [ /* ... */ ] }, { test: /.less$/, use: 'happypack/loader?id=styles' }, ] }; exports.plugins = [ // 2) create the plugin: new HappyPack({ // 3) re-add the loaders you replaced above in #1: loaders: [ 'babel-loader?presets[]=es2015' ], threadPool: happyThreadPool, id: 'babel' }), new HappyPack({ id: 'styles', threadPool: happyThreadPool, loaders: [ 'style-loader', 'css-loader', 'less-loader' ] }) ];
注意: 这部分,如果你是vueCli创建的项目,则不用配置, 内部已处理
关闭source map
生产环境关闭productionSourceMap
、css sourceMap
, 生产环境没必要打开这个
// vue.config.js const isProduction = process.env.NODE_ENV === 'production' // 判断是否是生产环境 module.exports = { productionSourceMap: !isProduction, //关闭生产环境下的SourceMap映射文件 css: { sourceMap: !isProduction, // css sourceMap 配置 loaderOptions: { ...其它代码 } }, ...其它代码 }
组件的按需加载配置
这里以ElementUi 为例, 其他组件库官网上会有对应说明, 大体上差不多
借助 babel-plugin-component,我们可以只引入需要的组件,以达到减小项目体积的目的。
npm install babel-plugin-component -D // .babelrc 或者 babel.config.js { "presets": [["es2015", { "modules": false }]], "plugins": [ [ "component", { "libraryName": "element-ui", "styleLibraryName": "theme-chalk" } ] ] }
如图,可以看到对比,
还有需要注意的是,如果你使用了自定义主题, 那么在babel的配置中如官网以下
解决Echarts打包后体积过大问题
从刚开始的图中,能看到, echarts占了很大的体积, 这不能接受
方案一
在index.html模板文件中引入cdn, 打包的时候webpack配置externals ,这样webpack就不会打这个包到vendors里,减少体积,缺点是cnd稳定性可能会有问题,而且是先请求cdn资源之后再请求自己服务器代码,非同源。pass
方案二
babel-plugin-equire
我见社区有这个按需引入echarts的插件, 不过我没研究过, 感兴趣的可以去试试,我选择的是方案三
方案三
在线定制echarts, 可以选择自己想要的功能,生成的js,就会小很多,
将生成的echarts.min.js引入到项目中,替换项目中的echarts引用
import echarts from 'echarts' 变成下面 import echarts from './plugins/echarts.min.js' 也可将这个js放到index.html里面, <script src="./static/lib/echarts.min.js"></script> 在main.js文件里面 Vue.prototype.$echarts = window.echarts 同时可以卸载调之前装的echarts npm unistall echarts
可以看到 还是很明显的变化的
接下来 再看看打包生成的report现状
可以看到pdf占比还是很大, 继续优化
Vue项目卡顿慢加载?这些优化技巧告诉你!(二):https://developer.aliyun.com/article/1415081