-
Notifications
You must be signed in to change notification settings - Fork 122
/
index.ts
112 lines (91 loc) · 3.46 KB
/
index.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
import { basename, posix, resolve } from 'path'
import { existsSync, readFileSync } from 'fs'
import type { ConfigEnv, PluginOption, UserConfig, ViteDevServer } from 'vite'
import createDebugger from 'debug'
import { cleanConfig, configOptionFromEnv } from './utils'
import { filterEntrypointsForRollup, loadConfiguration, resolveGlobs } from './config'
import { assetsManifestPlugin } from './manifest'
export * from './types'
// Public: The resolved project root.
export const projectRoot = configOptionFromEnv('root') || process.cwd()
// Internal: Additional paths to watch.
let watchAdditionalPaths: string[] = []
// Public: Vite Plugin to detect entrypoints in a Ruby app, and allows to load a shared JSON configuration file that can be read from Ruby.
export default function ViteRubyPlugin (): PluginOption[] {
return [
{
name: 'vite-plugin-ruby',
config,
configureServer,
},
assetsManifestPlugin(),
]
}
const debug = createDebugger('vite-plugin-ruby:config')
// Internal: Resolves the configuration from environment variables and a JSON
// config file, and configures the entrypoints and manifest generation.
function config (userConfig: UserConfig, env: ConfigEnv): UserConfig {
const config = loadConfiguration(env.mode, projectRoot, userConfig)
const { assetsDir, base, outDir, server, root, entrypoints, ssrBuild } = config
const isLocal = config.mode === 'development' || config.mode === 'test'
const rollupOptions = userConfig.build?.rollupOptions
let rollupInput = rollupOptions?.input
// Normalize any entrypoints provided by plugins.
if (typeof rollupInput === 'string')
rollupInput = { [rollupInput]: rollupInput }
const build = {
emptyOutDir: userConfig.build?.emptyOutDir ?? (ssrBuild || isLocal),
sourcemap: !isLocal,
...userConfig.build,
assetsDir,
manifest: !ssrBuild,
outDir,
rollupOptions: {
...rollupOptions,
input: {
...rollupInput,
...Object.fromEntries(filterEntrypointsForRollup(entrypoints)),
},
output: {
...outputOptions(assetsDir, ssrBuild),
...rollupOptions?.output,
},
},
}
const envDir = userConfig.envDir || projectRoot
debug({ base, build, envDir, root, server, entrypoints: Object.fromEntries(entrypoints) })
watchAdditionalPaths = resolveGlobs(projectRoot, root, config.watchAdditionalPaths || [])
const alias = { '~/': `${root}/`, '@/': `${root}/` }
return cleanConfig({
resolve: { alias },
base,
envDir,
root,
server,
build,
viteRuby: config,
})
}
// Internal: Allows to watch additional paths outside the source code dir.
function configureServer (server: ViteDevServer) {
server.watcher.add(watchAdditionalPaths)
return () => server.middlewares.use((req, res, next) => {
if (req.url === '/index.html' && !existsSync(resolve(server.config.root, 'index.html'))) {
res.statusCode = 404
const file = readFileSync(resolve(__dirname, 'dev-server-index.html'), 'utf-8')
res.end(file)
}
next()
})
}
function outputOptions (assetsDir: string, ssrBuild: boolean) {
// Internal: Avoid nesting entrypoints unnecessarily.
const outputFileName = (ext: string) => ({ name }: { name: string }) => {
const shortName = basename(name).split('.')[0]
return posix.join(assetsDir, `${shortName}-[hash].${ext}`)
}
return {
assetFileNames: ssrBuild ? undefined : outputFileName('[ext]'),
entryFileNames: ssrBuild ? undefined : outputFileName('js'),
}
}