-
Notifications
You must be signed in to change notification settings - Fork 921
/
Copy pathcreatePlugin.ts
136 lines (126 loc) · 4.03 KB
/
createPlugin.ts
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
import type { Plugin } from 'vite'
import createVuePlugin from '@vitejs/plugin-vue'
import type { App } from '@vuepress/core'
import { removeLeadingSlash } from '@vuepress/shared'
import { fs } from '@vuepress/utils'
import type { ViteBundlerOptions } from '../types'
import { createWorkaroundPlugin } from './createWorkaroundPlugin'
import { resolveAlias } from './resolveAlias'
import { resolveDefine } from './resolveDefine'
// packages that include client code, which should not
// be optimized nor externalized
const clientPackages = [
'@vuepress/client',
'@vuepress/plugin-active-header-links',
'@vuepress/plugin-back-to-top',
'@vuepress/plugin-container',
'@vuepress/plugin-debug',
'@vuepress/plugin-docsearch',
'@vuepress/plugin-git',
'@vuepress/plugin-google-analytics',
'@vuepress/plugin-medium-zoom',
'@vuepress/plugin-nprogress',
'@vuepress/plugin-palette',
'@vuepress/plugin-prismjs',
'@vuepress/plugin-pwa',
'@vuepress/plugin-pwa-popup',
'@vuepress/plugin-register-components',
'@vuepress/plugin-search',
'@vuepress/plugin-shiki',
'@vuepress/plugin-theme-data',
'@vuepress/plugin-toc',
'@vuepress/theme-default',
'@vuepress/theme-vue',
]
export const createPlugin = ({
app,
options,
isServer,
isBuild,
}: {
app: App
options: ViteBundlerOptions
isServer: boolean
isBuild: boolean
}): Plugin[] => [
createVuePlugin(options.vuePluginOptions),
createWorkaroundPlugin(),
{
name: 'vuepress',
config: async () => ({
root: app.dir.source(),
base: app.options.base,
mode: isBuild ? 'production' : 'development',
define: await resolveDefine({ app, isServer }),
publicDir: app.dir.public(),
cacheDir: app.dir.cache(),
resolve: {
alias: await resolveAlias({ app }),
},
server: {
host: app.options.host,
port: app.options.port,
open: app.options.open,
},
build: {
ssr: isServer,
outDir: isServer ? app.dir.dest('.server') : app.dir.dest(),
cssCodeSplit: false,
// TODO: may need to add this polyfill
polyfillDynamicImport: false,
rollupOptions: {
input: app.dir.client('lib/app.js'),
preserveEntrySignatures: 'allow-extension',
},
minify: isServer ? false : !app.env.isDebug,
},
optimizeDeps: {
include: ['@vuepress/shared'],
exclude: clientPackages,
},
ssr: {
noExternal: clientPackages,
},
}),
async configureServer(server) {
// here we need to import vite client script explicitly because we do not
// have the `index.html` file as a normal vite app
const viteClient = `${app.options.base}@vite/client`
// resolve the url path of the client entry file
// use `removeLeadingSlash` to compat with windows file path
const clientEntry = `${app.options.base}@fs/${removeLeadingSlash(
app.dir.client('lib/app.js')
)}`
// resolve the module of client entry to get the timestamp
const clientEntryModule = await server.moduleGraph.ensureEntryFromUrl(
clientEntry
)
return () => {
server.middlewares.use((req, res, next) => {
if (req.url!.endsWith('.html')) {
res.statusCode = 200
// load dev template file
const template = fs.readFileSync(app.options.templateDev).toString()
// inject timestamp to client entry
const clientEntrySrc =
clientEntryModule.lastHMRTimestamp > 0
? `${clientEntry}?t=${clientEntryModule.lastHMRTimestamp}`
: clientEntry
// inject client entry to dev template
res.end(
template.replace(
/<\/body>/,
`${[
`<script type="module" src="${viteClient}"></script>`,
`<script type="module" src="${clientEntrySrc}"></script>`,
].join('')}</body>`
)
)
return
}
next()
})
}
},
},
]