vue预渲染 render-spa-plugin
-
全局安装
1npm install -g @vue/cli-init -
创建vebpack项目
vue init webpack . // 在当前文件夹下创建项目 1
2
3
4
5
6
7
8
9
10? Generate project in current directory? Yes
? Project name prerender-spa
? Project description A Vue.js project
? Author dxc1996 <[email protected]>
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? No
? Set up unit tests No
? Setup e2e tests with Nightwatch? No
? Should we run `npm install` for you after the project has been created? (recommended) npm -
安装插件
1npm/cnpm i prerender-spa-plugin -D -
路由模式要为
history 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
import About from '@/components/About'
import Test from '@/components/Test'
Vue.use(Router)
export default new Router({<!-- -->
mode:'history',
routes: [
{<!-- -->path: '/',name: 'Home',component: Home},
{<!-- -->path: '/about',name: 'About',component: About},
{<!-- -->path: '/test',name: 'Test',component: Test}
]
})这是我的目录结构
-
在webpack.prod.config.js下配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20const PrerenderSPAPlugin = require('prerender-spa-plugin');
// 调用渲染器
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer
plugins:[
...
//调用渲染器
new PrerenderSPAPlugin({<!-- -->
staticDir: path.join(__dirname, '../dist'),
// Required - Routes to render.
routes: [ '/', '/about'],
renderer: new Renderer({<!-- -->
inject: {<!-- -->
foo: 'bar'
},
headless: false,
// 在项目的入口使用document.dispatchEvent(new Event('render-event'))
renderAfterDocumentEvent: 'render-event',
})
})
]整体来说是这样的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const PrerenderSPAPlugin = require('prerender-spa-plugin');
// 调用渲染器
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer
const env = require('../config/prod.env')
const webpackConfig = merge(baseWebpackConfig, {<!-- -->
module: {<!-- -->
rules: utils.styleLoaders({<!-- -->
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {<!-- -->
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({<!-- -->
'process.env': env
}),
new UglifyJsPlugin({<!-- -->
uglifyOptions: {<!-- -->
compress: {<!-- -->
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({<!-- -->
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({<!-- -->
cssProcessorOptions: config.build.productionSourceMap
? {<!-- --> safe: true, map: {<!-- --> inline: false } }
: {<!-- --> safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({<!-- -->
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {<!-- -->
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({<!-- -->
name: 'vendor',
minChunks (module) {<!-- -->
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({<!-- -->
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({<!-- -->
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{<!-- -->
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
]),
//调用渲染器
new PrerenderSPAPlugin({<!-- -->
// Required - The path to the webpack-outputted app to prerender.
staticDir: path.join(__dirname, '../dist'),
// Required - Routes to render.
routes: [ '/', '/about'],
renderer: new Renderer({<!-- -->
// Optional - Any values you'd like your app to have access to via `window.injectProperty`.
inject: {<!-- -->
foo: 'bar'
},
// Other puppeteer options.
// (See here: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions)
headless: false, // Display the browser window when rendering. Useful for debugging.
// Optional - Wait to render until the specified event is dispatched on the document.
// eg, with `document.dispatchEvent(new Event('custom-render-trigger'))`
// 在项目的入口使用document.dispatchEvent(new Event('render-event'))
renderAfterDocumentEvent: 'render-event',
})
})
]
})
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
})
)
}
if (config.build.bundleAnalyzerReport) {<!-- -->
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig -
配置main.js
1
2
3
4
5
6
7
8
9new Vue({<!-- -->
el: '#app',
router,
components: {<!-- --> App },
template: '<App/>',
mounted(){<!-- -->
document.dispatchEvent(new Event('render-event'))
}
}) -
打包后的文件
如有雷同,请联系删除