整个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配置的更改;
后面自己实验后,补充这个插件的注意事项