1 | const path = require('path')
|
2 | const fs = require('fs-extra')
|
3 |
|
4 | exports.name = 'vue-static'
|
5 |
|
6 | exports.apply = (api, { staticRoutes, resourceHints = true } = {}) => {
|
7 | if (
|
8 | !api.hasDependency('vue') ||
|
9 | !api.hasDependency('vue-template-compiler')
|
10 | ) {
|
11 | throw new api.PoiError({
|
12 | message: `You must have both "vue" and "vue-template-compiler" installed in your project`
|
13 | })
|
14 | }
|
15 |
|
16 | api.hook('createConfig', config => {
|
17 | if (!Array.isArray(config.entry) && typeof config.entry === 'object') {
|
18 | throw new api.PoiError({
|
19 | message: `When using plugin vue-static, the value of \`entry\` option cannot be an object`
|
20 | })
|
21 | }
|
22 |
|
23 | if (Array.isArray(config.entry) && config.entry.length > 1) {
|
24 | api.logger.warn(
|
25 | `\`entry\` is an array, however we only use the first item in vue-static plugin`
|
26 | )
|
27 | }
|
28 |
|
29 | config.babel.jsx = 'vue'
|
30 | })
|
31 |
|
32 | api.hook('createWebpackChain', (config, { type }) => {
|
33 |
|
34 | config.entryPoints.clear()
|
35 |
|
36 | config.entry('index').add(path.join(__dirname, `app/entry-${type}.js`))
|
37 |
|
38 | config.resolve.alias.set(
|
39 | '#user-entry$',
|
40 | api.resolveCwd(
|
41 | Array.isArray(api.config.entry) ? api.config.entry[0] : api.config.entry
|
42 | )
|
43 | )
|
44 |
|
45 | config.output.path(api.resolveCwd(`.vue-static/${type}`))
|
46 |
|
47 |
|
48 | config.plugin('vue-ssr').use(require(`vue-server-renderer/${type}-plugin`))
|
49 |
|
50 | config.module.rule('js').include.add(path.join(__dirname, 'app'))
|
51 |
|
52 | if (type === 'server') {
|
53 | config.output.libraryTarget('commonjs2')
|
54 | config.target('node')
|
55 | const externals = config.get('externals')
|
56 | config.externals(
|
57 | [
|
58 | require('webpack-node-externals')({
|
59 | whitelist: [/\.(?!(?:jsx?|json)$).{1,5}$/i]
|
60 | })
|
61 | ].concat(externals || [])
|
62 | )
|
63 | config.optimization.splitChunks(false)
|
64 | config.optimization.runtimeChunk(false)
|
65 | }
|
66 |
|
67 | if (!api.cli.options.serve) {
|
68 | config
|
69 | .plugin('html')
|
70 | .tap(([options]) => [
|
71 | Object.assign(options, { inject: false, minify: false })
|
72 | ])
|
73 | }
|
74 |
|
75 | config.plugin('constants').tap(([options]) => [
|
76 | Object.assign({}, options, {
|
77 | 'process.server': type === 'server',
|
78 | 'process.browser': type === 'client',
|
79 | 'process.client': type === 'client'
|
80 | })
|
81 | ])
|
82 |
|
83 | config.plugin('print-status').tap(([options]) => [
|
84 | Object.assign(options, {
|
85 | printFileStats: false
|
86 | })
|
87 | ])
|
88 | })
|
89 |
|
90 | api.hook('createCLI', ({ command }) => {
|
91 |
|
92 | const defaultAction = command.commandAction
|
93 | command.action(async (...args) => {
|
94 | if (api.cli.options.serve) {
|
95 |
|
96 |
|
97 | await defaultAction(...args)
|
98 | } else {
|
99 |
|
100 |
|
101 | const clientConfig = api
|
102 | .createWebpackChain({ type: 'client' })
|
103 | .toConfig()
|
104 | const serverConfig = api
|
105 | .createWebpackChain({ type: 'server' })
|
106 | .toConfig()
|
107 | const [clientStats, serverStats] = await Promise.all([
|
108 | api.runCompiler(api.createWebpackCompiler(clientConfig)),
|
109 | api.runCompiler(api.createWebpackCompiler(serverConfig))
|
110 | ])
|
111 | if (clientStats.hasErrors() || serverStats.hasErrors()) {
|
112 | return
|
113 | }
|
114 | await fs.copy(api.resolveCwd(`.vue-static/client`), api.resolveOutDir())
|
115 | await require('./generate')(api, {
|
116 | serverBundle: require(api.resolveCwd(
|
117 | '.vue-static/server/vue-ssr-server-bundle.json'
|
118 | )),
|
119 | clientManifest: require(api.resolveCwd(
|
120 | '.vue-static/client/vue-ssr-client-manifest.json'
|
121 | )),
|
122 | staticRoutes,
|
123 | resourceHints,
|
124 | htmlSkeletion: await fs.readFile(
|
125 | api.resolveCwd('.vue-static/client/index.html'),
|
126 | 'utf8'
|
127 | )
|
128 | })
|
129 | await Promise.all([
|
130 | fs.remove(api.resolveCwd('.vue-static')),
|
131 | fs.remove(api.resolveOutDir('vue-ssr-client-manifest.json'))
|
132 | ])
|
133 | api.logger.done(
|
134 | `Successfully generated into ${path.relative(
|
135 | process.cwd(),
|
136 | api.resolveOutDir()
|
137 | )}`
|
138 | )
|
139 | }
|
140 | })
|
141 | })
|
142 | }
|