• 图片压缩:使用图片图片压缩、优化工具TinyPNG、TinyJPG压缩图片,或者使用其Gulp 组件 gulp-tinypng 结合到自动化构件流程中;
  • 图片格式转为base64: 使用webpack的 url-loader ,自动根据文件大小决定要不要做成内联 base64;
  • 图片懒加载: vue.js可用使用 vue-lazyload ;
  • 2、CDN优化

  • 将依赖的静态资源如 vue vue-router vuex 等,全部改为通过CDN链接获取。
  • 借助HtmlWebpackPlugin,可以方便的使用循环语法在index.html里插入js和css的CDN链接。推荐CDN使用 jsDelivr 提供的。
  • index.html 文件中
  • <!-- 使用CDN加速的CSS文件,配置在vue.config.js下 -->
    <% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %>
    <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style">
    <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet">
    <% } %>
    <!-- 使用CDN加速的JS文件,配置在vue.config.js下 -->
    <% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
    <link href="<%= htmlWebpackPlugin.options.cdn.js[i] %>" rel="preload" as="script">
    <% } %>
    
  • vue.config.js下添加如下代码,这使得在使用CDN引入外部文件的情况下,依然可以在项目中使用import的语法来引入这些第三方库,也就意味着你不需要改动项目的代码
  • // 转为CDN外链方式的npm包,键名是引入的npm包名,键值是该库暴露的全局变量
    const externals = {
        vue: 'Vue',
        'vue-router': 'VueRouter',
        vuex: 'Vuex',
        axios: 'axios',
        vant: 'vant',
        'pdfjs-dist': 'pdfjs',
    // 添加CDN参数到htmlWebpackPlugin配置中;
            config.plugin('html').tap((args) => {
                if (process.env.NODE_ENV === 'production') {
                    args[0].cdn = CDN.build;
                return args;
    复制代码

    3、Prerender 预渲染

    4、Gzip 优化

  • 后台开启gzip压缩,以nginx服务器为例
  • # 开启和关闭gzip模式
        gzip on;
        # nginx对于静态文件的处理模块,开启后会寻找以.gz结尾的文件,直接返回,不会占用cpu进行压缩,如果找不到则不进行压缩
        gzip_static on;
        # gizp压缩起点,文件大于1k才进行压缩
    	gzip_min_length 1k;
        # 设置压缩所需要的缓冲区大小,以4k为单位,如果文件为7k则申请2*4k的缓冲区 
    	gzip_buffers 4 16k;
        # gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时
    	gzip_comp_level 2;
        # 进行压缩的文件类型。
    	gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;
        # 是否在http header中添加Vary: Accept-Encoding,建议开启
        gzip_vary on;
        # 禁用IE 6 gzip
    	gzip_disable "MSIE [1-6]\.";
    
  • 前端gzip压缩
  • nginx设置gzip_static on,就会使用同名的.gz文件,不会占用服务器的CPU资源去压缩
  • const CompressionPlugin = require('compression-webpack-plugin');
    configureWebpack: () => {
            if (process.env.NODE_ENV === 'production') {
                // 开启gzip压缩 同名的.gz文件 不会占用服务器的CPU资源去压缩
                const compressionTest = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i;
                return {
                    plugins: [
                        new CompressionPlugin({
                            test: compressionTest, // 匹配文件名
                            minRatio: 0.99, // 压缩率
    复制代码
    const path = require('path')
    const chalk = require('chalk')
    const CompressionWebpackPlugin = require('compression-webpack-plugin')
    const PrerenderSPAPlugin = require('prerender-spa-plugin')
    // 存放build结果的文件夹(主要是为了填prerender在配置了baseUrl后带来的坑,下面会说)
    const DIST_ROOT = 'dist'
    // 项目部署在服务器里的绝对路径,默认'/',参考https://cli.vuejs.org/zh/config/#baseurl
    const BASE_URL = '/my-app/'
    // 转为CND外链方式的npm包,键名是import的npm包名,键值是该库暴露的全局变量,参考https://webpack.js.org/configuration/externals/#src/components/Sidebar/Sidebar.jsx
    const externals = {
      'vue': 'Vue',
      'vue-router': 'VueRouter',
      'vuex': 'Vuex',
      'axios': 'axios',
      'element-ui': 'ELEMENT'
    // CDN外链,会插入到index.html中
    const cdn = {
      // 开发环境
      dev: {
        css: [
          'https://unpkg.com/element-ui/lib/theme-chalk/index.css'
        js: []
      // 生产环境
      build: {
        css: [
          'https://unpkg.com/element-ui/lib/theme-chalk/index.css'
        js: [
          'https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.min.js',
          'https://cdn.jsdelivr.net/npm/vue-router@3.0.1/dist/vue-router.min.js',
          'https://cdn.jsdelivr.net/npm/vuex@3.0.1/dist/vuex.min.js',
          'https://cdn.jsdelivr.net/npm/axios@0.18.0/dist/axios.min.js',
          'https://unpkg.com/element-ui/lib/index.js'
    // 是否使用预渲染
    const productionPrerender = true
    // 需要预渲染的路由
    const prerenderRoutes = ['/', '/contacts']
    // 是否使用gzip
    const productionGzip = true
    // 需要gzip压缩的文件后缀
    const productionGzipExtensions = ['js', 'css']
    module.exports = {
      baseUrl: BASE_URL,
      outputDir: DIST_ROOT + BASE_URL, // prerendner会借助一个express服务器来预渲染,改变baseUrl后要保证这个模拟服务器能够找到所需的资源
      assetsDir: 'static',
      productionSourceMap: false,
      configureWebpack: config => {
        const myConfig = {}
        if (process.env.NODE_ENV === 'production') {
          // 1. 生产环境npm包转CDN
          myConfig.externals = externals
          // 2. 使用预渲染,在仅加载html和css之后即可显示出基础的页面,提升用户体验,避免白屏
          myConfig.plugins = []
          productionPrerender && myConfig.plugins.push(
            new PrerenderSPAPlugin({
              staticDir: path.resolve(__dirname, DIST_ROOT), // 作为express.static()中间件的路径
              outputDir: path.resolve(__dirname, DIST_ROOT + BASE_URL),
              indexPath: path.resolve(__dirname, DIST_ROOT + BASE_URL + 'index.html'),
              routes: prerenderRoutes,
              minify: {
                collapseBooleanAttributes: true,
                collapseWhitespace: true,
                decodeEntities: true,
                keepClosingSlash: true,
                sortAttributes: true
              postProcess (renderedRoute) {
                 * 懒加载模块会自动注入,无需直接通过script标签引入
                 * 而且预渲染的html注入的是modern版本的懒加载模块
                 * 这会导致在低版本浏览器出现报错,需要剔除
                 * 这并不是一个非常严谨的正则,不适用于使用了 webpackChunkName: "group-foo" 注释的懒加载
                renderedRoute.html = renderedRoute.html.replace(
                  /<script[^<]*chunk-[a-z0-9]{8}\.[a-z0-9]{8}.js[^<]*><\/script>/g,
                  function (target) {
                    console.log(chalk.bgRed('\n\n剔除的懒加载标签:'), chalk.magenta(target))
                    return ''
                return renderedRoute
          // 3. 构建时开启gzip,降低服务器压缩对CPU资源的占用,服务器也要相应开启gzip
          productionGzip && myConfig.plugins.push(
            new CompressionWebpackPlugin({
              test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
              threshold: 8192,
              minRatio: 0.8
        if (process.env.NODE_ENV === 'development') {
           * 关闭host check,方便使用ngrok之类的内网转发工具
          myConfig.devServer = {
            disableHostCheck: true
        return myConfig
      chainWebpack: config => {
         * 删除懒加载模块的prefetch,降低带宽压力
         * https://cli.vuejs.org/zh/guide/html-and-static-assets.html#prefetch
         * 而且预渲染时生成的prefetch标签是modern版本的,低版本浏览器是不需要的
        config.plugins
          .delete('prefetch')
         * 添加CDN参数到htmlWebpackPlugin配置中
        config
          .plugin('html')
          .tap(args => {
            if (process.env.NODE_ENV === 'production') {
              args[0].cdn = cdn.build
            if (process.env.NODE_ENV === 'development') {
              args[0].cdn = cdn.dev
            return args
         * 无需使用@import在每个scss文件中引入变量或者mixin,也可以避免大量@import导致build变慢
         * sass-resources-loader 文档链接:https://github.com/shakacode/sass-resources-loader
        const oneOfsMap = config.module.rule('scss').oneOfs.store
        const sassResources = ['color.scss', 'mixin.scss', 'common.scss'] // scss资源文件,可以在里面定义变量,mixin,全局混入样式等
        oneOfsMap.forEach(item => {
            .use('sass-resources-loader')
            .loader('sass-resources-loader')
            .options({
              resources: sassResources.map(file => path.resolve(__dirname, 'src/style/' + file))
            .end()
    复制代码
    分类:
    前端
    标签: