Vue-cli4x项目优化实践

1.关闭productionSourceMap

最新件脚手架不自带配置文件
先在根目录新建vue.config.js文件,在vue.config.js中写入如下内容:

module.exports = {
    productionSourceMap: false
}

2.开启Gzip压缩

安装插件compression-webpack-plugin。这个插件必须配合后台,服务器上nginx也必须开启gzip才能生效

npm install --save-dev compression-webpack-plugin
// 是否为生产环境
const isProduction = process.env.NODE_ENV !== 'development';

// gzip压缩
const CompressionWebpackPlugin = require('compression-webpack-plugin')
module.exports = {
    productionSourceMap: false,
    configureWebpack: config => {
        // 生产环境相关配置
        if (isProduction) {
            //gzip压缩
            config.plugins.push(
                new CompressionWebpackPlugin({
                    filename: '[path].gz[query]',
                    algorithm: 'gzip',
                    test: /\.js$|\.html$|.\css/,
                    threshold: 10240, // 只有大小大于该值的资源会被处理 10240
                    minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理
                    deleteOriginalAssets: false // 删除原文件
                })
            )
        }
    },
}

3.开启CDN加速(有可能cdn会挂掉,也可以不配置这选项)

// 本地环境是否需要使用cdn
const devNeedCdn = false
// 是否为生产环境
const isProduction = process.env.NODE_ENV !== 'development';
// cdn链接
const cdn = {
  // cdn:模块名称和模块作用域命名(对应window里面挂载的变量名称)
  externals: {
    vue: "Vue",
    vuex: "Vuex",
    "vue-router": "VueRouter",
    axios: "axios",
    vant: "vant",
  },
  //
  // cdn的css链接
  css: ["https://cdn.jsdelivr.net/npm/vant@2.10/lib/index.css"],
  // cdn的js链接
  js: [
    "https://cdn.jsdelivr.net/npm/vue@2.6/dist/vue.min.js",
    "https://cdn.jsdelivr.net/npm/vuex@3.5.1/dist/vuex.min.js",
    "https://cdn.jsdelivr.net/npm/vue-router@3.4.9/dist/vue-router.min.js",
    "https://cdn.jsdelivr.net/npm/vant@2.10/lib/vant.min.js",
    "https://cdn.jsdelivr.net/npm/axios@0.21.0/dist/axios.min.js",
  ],
};

module.exports = {
    chainWebpack: config => {
        config.plugin('html').tap(args => {
            // 生产环境或本地需要cdn时,才注入cdn
            if (isProduction || devNeedCdn) args[0].cdn = cdn
            return args
        })
        
    },
    configureWebpack: config => {
        // 用cdn方式引入,则构建时要忽略相关资源
        if (isProduction || devNeedCdn) config.externals = cdn.externals
    }
}

然后在index.html中引入使用了CDN的链接(使用了loading动画,刷新时不会出现空白加载)

<html lang="en" style="width: 100%;height: 100%;">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <style>
		#vue-loading{
      background-color: #fff;
      height: 100%;
      width: 100%;
      position: fixed;
      z-index: 99999;
      margin-top: 0px;
      top: 0px;
    }
    #loading-center{
      width: 100%;
      height: 100%;
      position: relative;
      }
    #loading-center-absolute {
      position: absolute;
      left: 50%;
      top: 50%;
      height: 150px;
      width: 150px;
      margin-top: -75px;
      margin-left: -75px;	
      -ms-transform: rotate(45deg); 
        -webkit-transform: rotate(45deg);
        transform: rotate(45deg); 
    }
    .object{
      width: 20px;
      height: 20px;
      background-color:#eb8819;
      position: absolute;
      left: 65px;
      top: 65px;
      }
    .object:nth-child(2n+0) {
      margin-right: 0px;
    }
    #object_one {
      -webkit-animation: object_one 2s infinite;
      animation: object_one 2s infinite;
      -webkit-animation-delay: 0.2s; 
        animation-delay: 0.2s; 
      }
    #object_two {
      -webkit-animation: object_two 2s infinite;
      animation: object_two 2s infinite;
      -webkit-animation-delay: 0.3s; 
        animation-delay: 0.3s; 
      }
    #object_three {
      -webkit-animation: object_three 2s infinite;
      animation: object_three 2s infinite;
      -webkit-animation-delay: 0.4s; 
        animation-delay: 0.4s; 
      }
    #object_four {
      -webkit-animation: object_four 2s infinite;
      animation: object_four 2s infinite;
      -webkit-animation-delay: 0.5s; 
        animation-delay: 0.5s; 
    }
    #object_five {
      -webkit-animation: object_five 2s infinite;
      animation: object_five 2s infinite;
      -webkit-animation-delay: 0.6s; 
        animation-delay: 0.6s; 
    }
    #object_six {
      -webkit-animation: object_six 2s infinite;
      animation: object_six 2s infinite;
      -webkit-animation-delay: 0.7s; 
        animation-delay: 0.7s; 
    }
    #object_seven {
      -webkit-animation: object_seven 2s infinite;
      animation: object_seven 2s infinite;
      -webkit-animation-delay: 0.8s; 
        animation-delay: 0.8s; 
    }
    #object_eight {
      -webkit-animation: object_eight 2s infinite;
      animation: object_eight 2s infinite;
      -webkit-animation-delay: 0.9s; 
        animation-delay: 0.9s; 
    }
    #object_big{
      position: absolute;
      width: 50px;
      height: 50px;
      left: 50px;
      top: 50px;
      -webkit-animation: object_big 2s infinite;
      animation: object_big 2s infinite;
      -webkit-animation-delay: 0.5s; 
        animation-delay: 0.5s; 
    }	
    @-webkit-keyframes object_big {
    50% { -webkit-transform: scale(0.5); }
    }
    @keyframes object_big {
    50% { 
        transform: scale(0.5);
        -webkit-transform: scale(0.5);
      } 
    }
    @-webkit-keyframes object_one {
    50% { -webkit-transform: translate(-65px,-65px)  ; }
    }
    @keyframes object_one {
    50% { 
        transform: translate(-65px,-65px) ;
        -webkit-transform: translate(-65px,-65px) ;
      } 
    }
    @-webkit-keyframes object_two {
      50% { -webkit-transform: translate(0,-65px) ; }
    }
    @keyframes object_two {
    50% { 
        transform: translate(0,-65px) ; 
        -webkit-transform: translate(0,-65px) ; 
      } 
    }
    @-webkit-keyframes object_three {
    50% { -webkit-transform: translate(65px,-65px) ; }
    }
    @keyframes object_three {
    50% { 
        transform: translate(65px,-65px) ;
        -webkit-transform: translate(65px,-65px) ;
      } 
    }
    @-webkit-keyframes object_four {
      
      50% { -webkit-transform: translate(65px,0) ; }

    }
    @keyframes object_four {
      50% { 
        transform: translate(65px,0) ;
        -webkit-transform: translate(65px,0) ;
      } 
    }
    @-webkit-keyframes object_five {

      50% { -webkit-transform: translate(65px,65px) ; }
    }
    @keyframes object_five {
      50% { 
        transform: translate(65px,65px) ;
        -webkit-transform: translate(65px,65px) ;
      } 
    }

    @-webkit-keyframes object_six {
      50% { -webkit-transform: translate(0,65px) ; }
    }

    @keyframes object_six {
      50% { 
        transform:  translate(0,65px) ;
        -webkit-transform:  translate(0,65px) ;
      } 
    }
    @-webkit-keyframes object_seven {
      50% { -webkit-transform: translate(-65px,65px) ; }
    }
    @keyframes object_seven {
      50% { 
        transform: translate(-65px,65px) ;
        -webkit-transform: translate(-65px,65px) ;
      } 
    }
    @-webkit-keyframes object_eight {
      50% { -webkit-transform: translate(-65px,0)} ; 
    }
    @keyframes object_eight {
      50% { 
        transform: translate(-65px,0) ;
        -webkit-transform: translate(-65px,0) ;
      } 
    }
	</style>
    <!-- 使用CDN的CSS文件 -->
    <% for (var i in htmlWebpackPlugin.options.cdn &&
    htmlWebpackPlugin.options.cdn.css) { %>
    <link
            href="<%= htmlWebpackPlugin.options.cdn.css[i] %>"
            rel="stylesheet"
    />
    <% } %>
    <!-- 使用CDN的CSS文件 -->
    
    <title>人人家智慧社区</title>
  </head>
  <body style="width: 100%;height: 100%;">
    <noscript>
      <strong>We're sorry but blog doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="vue-loading">
      <div id="loading-center">
        <div id="loading-center-absolute">
          <div class="object" id="object_one"></div>
          <div class="object" id="object_two"></div>
          <div class="object" id="object_three"></div>
          <div class="object" id="object_four"></div>
          <div class="object" id="object_five"></div>
          <div class="object" id="object_six"></div>
          <div class="object" id="object_seven"></div>
          <div class="object" id="object_eight"></div>
          <div class="object" id="object_big"></div>
        </div>
      </div>
    </div>
    <div id="app"></div>
    <!-- built files will be auto injected -->

    <!-- 使用CDN的JS文件 -->
    <% for (var i in htmlWebpackPlugin.options.cdn &&
    htmlWebpackPlugin.options.cdn.js) { %>
    <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
    <% } %>
    <!-- 使用CDN的JS文件 -->
      <script>
        window.onload=function(){
          if(document.querySelector("#vue-loading") !==undefined){
            document.querySelector("#vue-loading").remove()
          }
        }
      </script>
  </body>
</html>

4.代码压缩

安装

npm i -D uglifyjs-webpack-plugin
// 代码压缩
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
config.plugins.push(
    new UglifyJsPlugin({
        uglifyOptions: {
            //生产环境自动删除console
            compress: {
                drop_debugger: true,
                drop_console: true,
                pure_funcs: ['console.log']
            }
        },
        sourceMap: false,
        parallel: true
    })
)
5.公共代码抽离,写在configureWebpack模块中
// 公共代码抽离
configureWebpack: config => {
    // 生产环境相关配置
    if (isProduction) {
        config.optimization = {
		    splitChunks: {
		        cacheGroups: {
		            vendor: {
		                chunks: 'all',
		                test: /node_modules/,
		                name: 'vendor',
		                minChunks: 1,
		                maxInitialRequests: 5,
		                minSize: 0,
		                priority: 100
		            },
		            common: {
		                chunks: 'all',
		                test: /[\\/]src[\\/]js[\\/]/,
		                name: 'common',
		                minChunks: 2,
		                maxInitialRequests: 5,
		                minSize: 0,
		                priority: 60
		            },
		            styles: {
		                name: 'styles',
		                test: /\.(sa|sc|c)ss$/,
		                chunks: 'all',
		                enforce: true
		            },
		            runtimeChunk: {
		                name: 'manifest'
		            }
		        }
		    }
		}
    }
},

6.图片压缩()

安装

npm i image-webpack-loader --save-dev

在chainWebpack中新增以下代码

  configureWebpack: config => {
      // 生产环境相关配置
      if (isProduction) {
          config.module.rule('images')
		    .use('image-webpack-loader')
		    .loader('image-webpack-loader')
		    .options({ bypassOnDebug: true })
		    .end()
      }
  },

6.最终代码

// 是否为生产环境
const isProduction = process.env.NODE_ENV !== 'development';

// 代码压缩
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')

// gzip压缩
const CompressionWebpackPlugin = require('compression-webpack-plugin')
//path引入
const path = require('path')

// 本地环境是否需要使用cdn
const devNeedCdn = false

// cdn链接
const cdn = {
  // cdn:模块名称和模块作用域命名(对应window里面挂载的变量名称)
  externals: {
    vue: "Vue",
    vuex: "Vuex",
    "vue-router": "VueRouter",
    axios: "axios",
    vant: "vant",
  },
  //
  // cdn的css链接
  css: ["https://cdn.jsdelivr.net/npm/vant@2.10/lib/index.css"],
  // cdn的js链接
  js: [
    "https://cdn.jsdelivr.net/npm/vue@2.6/dist/vue.min.js",
    "https://cdn.jsdelivr.net/npm/vuex@3.5.1/dist/vuex.min.js",
    "https://cdn.jsdelivr.net/npm/vue-router@3.4.9/dist/vue-router.min.js",
    "https://cdn.jsdelivr.net/npm/vant@2.10/lib/vant.min.js",
    "https://cdn.jsdelivr.net/npm/axios@0.21.0/dist/axios.min.js",
  ],
};

module.exports = {
    productionSourceMap: false,
    chainWebpack: config => {
        // ============注入cdn start============
        config.plugin('html').tap(args => {
            // 生产环境或本地需要cdn时,才注入cdn
            if (isProduction || devNeedCdn) args[0].cdn = cdn
            return args
        })
        // ============注入cdn start============

        // ============压缩图片 start============
        config.module
            .rule('images')
            .use('image-webpack-loader')
            .loader('image-webpack-loader')
            .options({ bypassOnDebug: true })
            .end()
        // ============压缩图片 end============
    },
    configureWebpack: config => {
        // 用cdn方式引入,则构建时要忽略相关资源
        if (isProduction || devNeedCdn) config.externals = cdn.externals

        // 生产环境相关配置
        if (isProduction) {
            //gzip压缩
            config.plugins.push(
                new CompressionWebpackPlugin({
                    filename: '[path].gz[query]',
                    algorithm: 'gzip',
                    test:/\.js$|\.html$|.\css/,
                    threshold: 10240, // 只有大小大于该值的资源会被处理 10240
                    minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理
                    deleteOriginalAssets: false // 删除原文件
                })
            )

            // 代码压缩
            config.plugins.push(
                new UglifyJsPlugin({
                    uglifyOptions: {
                        //生产环境自动删除console
                        compress: {
                            drop_debugger: true,
                            drop_console: true,
                            pure_funcs: ['console.log']
                        }
                    },
                    sourceMap: false,
                    parallel: true
                })
            )
        }

        // 公共代码抽离
        config.optimization = {
            splitChunks: {
                cacheGroups: {
                    vendor: {
                        chunks: 'all',
                        test: /node_modules/,
                        name: 'vendor',
                        minChunks: 1,
                        maxInitialRequests: 5,
                        minSize: 0,
                        priority: 100
                    },
                    common: {
                        chunks: 'all',
                        test: /[\\/]src[\\/]js[\\/]/,
                        name: 'common',
                        minChunks: 2,
                        maxInitialRequests: 5,
                        minSize: 0,
                        priority: 60
                    },
                    styles: {
                        name: 'styles',
                        test: /\.(sa|sc|c)ss$/,
                        chunks: 'all',
                        enforce: true
                    },
                    runtimeChunk: {
                        name: 'manifest'
                    }
                }
            }
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值