Vue项目性能优化的一次记录

整个1.路由懒加载

 {
            path: "/myPage",
            name: "MyPage",
            component: resolve => require.ensure([],() => resolve(require("@/page/myPage/index")),"MyPage"),
            meta: { noCache: true }
        }

这个方法会把原本打包到一个app.js文件分开成多个js文件打包,这样会减小单个文件的大小,但是不会减小整个js文件夹的大小。

通过这种方式可以做到按需加载,只加载单个页面的js文件。

2.打包文件中去掉map文件

config/index.js文件中,将productionSourceMap设置为false;

打包之后的app.js过大,另外还有一些生成的map文件。通过上述方式,我们可以先将多余的map文件去掉

build: {
    // Template for index.html
    index: path.resolve(__dirname, '../dist/index.html'),
    // Paths
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    // assetsPublicPath: './',

    /**
     * Source Maps
     */

    productionSourceMap: false,
    // https://webpack.js.org/configuration/devtool/#production
    devtool: '#source-map',

    // Gzip off by default as many popular static hosts such as
    // Surge or Netlify already gzip all static assets for you.
    // Before setting to `true`, make sure to:
    // npm install --save-dev compression-webpack-plugin
    productionGzip: true,
    productionGzipExtensions: ['js', 'css'],

    // Run the build command with an extra argument to
    // View the bundle analyzer report after build finishes:
    // `npm run build --report`
    // Set to `true` or `false` to always turn it on or off
    bundleAnalyzerReport: process.env.npm_config_report
  }
}

3.gzip压缩开启,会更大限度的压缩文件

gizp压缩是一种http请求优化方式,通过减少文件体积来提高加载速度。

html、js、css文件甚至json数据都可以用它压缩,可以减小60%以上的体积。

        3.1 npm install --save-dev compression-webpack-plugin 安装插件

        3.2  config/index.js中,将productionGzip设置为true,productionGzipExtensions设置为 ['js', 'css'],

        3.3 vue 2.x的话,webpack.prod.conf.js文件中,加上如下代码

        

if (config.build.productionGzip) {
  const CompressionWebpackPlugin = require('compression-webpack-plugin')

  webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp(
        '\\.(' +
        config.build.productionGzipExtensions.join('|') +
        ')$'
      ),
      threshold: 10240,
      minRatio: 0.8,
      // deleteOriginalAssets:true // 删除源文件,否则打包带有原js文件,两个同名文件一个js一个gz
    })
  )
}

注意这里的deleteOriginalAssets:true 我注释掉了,我是发现设置之后项目白屏了;

      3.4 在Vue 3.x,在vue.config.js中配置

        

const CompressionPlugin = require('compression-webpack-plugin')
configureWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
        return {
            plugins: [new CompressionPlugin({
                test: /\.js$|\.html$|\.css/,
                threshold: 10240,
                deleteOriginalAssets: false
            })]
        }
    }
}

 不过还需要云端人员或者运维人员在nginx配置支持一下;

4.CDN引入第三方库(BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务)

 <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.min.js"></script>
 <script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.0.2/vue-router.min.js"></script>
 <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.18.1/axios.min.js"></script>

我在项目里vue以及axios都使用了cdn引入,使用之后需要做下处理,不再直接import引用

build\webpack.base.conf.js,文件里面,增加如下配置

'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin');

function resolve (dir) {
  return path.join(__dirname, '..', dir)
}



module.exports = {
  context: path.resolve(__dirname, '../'),
  entry: {
    app: './src/main.js'
  },
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    }
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('media/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.less$/,
        loader: "style-loader!css-loader!less-loader",
      },
      {
          test: /\.sass$/,
          loaders: ['style', 'css', 'sass']
      }
    ]
  },
  plugins: [
    new CopyWebpackPlugin([
        { from: './src/html', to: "./" }
     ]),
  ],
  node: {
    // prevent webpack from injecting useless setImmediate polyfill because Vue
    // source contains it (although only uses it if it's native).
    setImmediate: false,
    // prevent webpack from injecting mocks to Node native modules
    // that does not make sense for the client
    dgram: 'empty',
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
    child_process: 'empty'
  },
 // 在此处增加配置
  externals: {
    'vue': 'Vue',
    'vue-router':'VueRouter',
    'axios':'axios'
 }
}

如果是vue 3.x,那么在在vue.config.js进行配置

configureWebpack:{
    externals: {
       'vue': 'Vue',
    'vue-router':'VueRouter',
    'axios':'axios'
    }
 }

main.js里面原先的 import Vue from 'vue',可以注释掉了;

router.js里面的

// import Vue from 'vue'

// import Router from 'vue-router'

也可以注释掉了;

const router = new Router({})--注释之前的使用;

const router = new VueRouter({});---注释之后的使用

网络请求的地方

 // import axios from 'axios',引入axios的也可以注释掉了;

当然cdn引入的不止这几个,其他合适的都可以引入

5.预渲染

预渲染就是在js加载前,就生成了一个首页的静态页面,用于加载,这样就会让用户很快看到内容,不用担心用户等待的不耐烦了;

预渲染,是把原来的单index.html,渲染成多个目录,每个目录又有一个index.html。这样就不需要内部重定向访问路由,也更利于搜索引擎收录。

预渲染我们使用prerender-spa-plugin插件,非常的简单,当然不仔细的话,还是会遇到坑

        原理是启动浏览器,渲染完成后抓取HTML,然后再创建目录,保存为index.html

        5.1   cnpm i puppeteer  cnpm i prerender-spa-plugin -D 安装插件

        5.2  在vue.config.js中配置

                

const PrerenderSPAPlugin = require('prerender-spa-plugin');
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer;
configureWebpack: {
	 plugins: [
  		new PrerenderSPAPlugin({
	 	// 生成文件的路径,也可以与webpakc打包的一致。
	 	// 下面这句话非常重要!!!
	 	// 这个目录只能有一级,如果目录层次大于一级,在生成的时候不会有任何错误提示,在预渲染的时候只会卡着不动。
			staticDir: path.join(__dirname,'dist'),
	  		// 对应自己的路由文件,比如a有参数,就需要写成 /a/param1。
	 		routes: ['/', '/team', '/analyst','/voter','/sponsor',],
	 		// 这个很重要,如果没有配置这段,也不会进行预编译
			renderer: new Renderer({
		         inject: {
					foo: 'bar'
		 		},
	   			headless: false,
			// 在 main.js 中 document.dispatchEvent(new Event('render-event')),两者的事件名称要对应上。
	 			renderAfterDocumentEvent: 'render-event',
				renderAfterTime: 10000,//超时时间
				timeout: 0,
				maxConcurrentRoutes: 20,//打包页面的最大数
				navigationParams: {
					timeout: 0
 				}
			})
		}),
 	]
}

PS:需要将路由模式设置为history模式

    5.3在main.js中,在创建vue实例的mounted里面加一个事件,跟PrerenderSPAPlugin实例里面的renderAfterDocumentEvent对应上。

new Vue({
  router,
  render: h => h(App),
  mounted () {
//追加触发器事件
  	document.dispatchEvent(new Event('render-event'))
  }
}).$mount("#app");

npm run build 一下,如果dist文件夹多了你想预渲染的文件夹,那么表示设置成功了;

如果项目是用nginx做的代理,nginx还需要做一些配置

location = / {
  try_files /home/index.html /index.html;
}
 //下面这个就不用了 因为有真实的目录
location / {
  try_files $uri $uri/ /index.html;
}

具体的根据自己需要欲渲染的路由自己配;

PS:踩坑

1、路由页面前两个页面不能有懒加载。

最后一个方式我是看到别人这么写的,自己还没实验过,涉及到nginx配置的更改;

后面自己实验后,补充这个插件的注意事项

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xvzhengyang

感谢,励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值