Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/build/vite/vite.config.ts
5257 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { createLogger, defineConfig, Plugin } from 'vite';
7
import path, { join } from 'path';
8
import { rollupEsmUrlPlugin } from '@vscode/rollup-plugin-esm-url';
9
import { statSync } from 'fs';
10
import { pathToFileURL } from 'url';
11
12
function injectBuiltinExtensionsPlugin(): Plugin {
13
let builtinExtensionsCache: unknown[] | null = null;
14
15
function replaceAllOccurrences(str: string, search: string, replace: string): string {
16
return str.split(search).join(replace);
17
}
18
19
async function loadBuiltinExtensions() {
20
if (!builtinExtensionsCache) {
21
builtinExtensionsCache = await getScannedBuiltinExtensions(path.resolve(__dirname, '../../'));
22
console.log(`Found ${builtinExtensionsCache!.length} built-in extensions.`);
23
}
24
return builtinExtensionsCache;
25
}
26
27
function asJSON(value: unknown): string {
28
return escapeHtmlByReplacingCharacters(JSON.stringify(value));
29
}
30
31
function escapeHtmlByReplacingCharacters(str: string) {
32
if (typeof str !== 'string') {
33
return '';
34
}
35
36
const escapeCharacter = (match: string) => {
37
switch (match) {
38
case '&': return '&';
39
case '<': return '&lt;';
40
case '>': return '&gt;';
41
case '"': return '&quot;';
42
case '\'': return '&#039;';
43
case '`': return '&#096;';
44
default: return match;
45
}
46
};
47
48
return str.replace(/[&<>"'`]/g, escapeCharacter);
49
}
50
51
const prebuiltExtensionsLocation = '.build/builtInExtensions';
52
async function getScannedBuiltinExtensions(vsCodeDevLocation: string) {
53
// use the build utility as to not duplicate the code
54
const extensionsUtil = await import(pathToFileURL(path.join(vsCodeDevLocation, 'build', 'lib', 'extensions.ts')).toString());
55
const localExtensions = extensionsUtil.scanBuiltinExtensions(path.join(vsCodeDevLocation, 'extensions'));
56
const prebuiltExtensions = extensionsUtil.scanBuiltinExtensions(path.join(vsCodeDevLocation, prebuiltExtensionsLocation));
57
for (const ext of localExtensions) {
58
let browserMain = ext.packageJSON.browser;
59
if (browserMain) {
60
if (!browserMain.endsWith('.js')) {
61
browserMain = browserMain + '.js';
62
}
63
const browserMainLocation = path.join(vsCodeDevLocation, 'extensions', ext.extensionPath, browserMain);
64
if (!fileExists(browserMainLocation)) {
65
console.log(`${browserMainLocation} not found. Make sure all extensions are compiled (use 'yarn watch-web').`);
66
}
67
}
68
}
69
return localExtensions.concat(prebuiltExtensions);
70
}
71
72
function fileExists(path: string): boolean {
73
try {
74
return statSync(path).isFile();
75
} catch (err) {
76
return false;
77
}
78
}
79
80
return {
81
name: 'inject-builtin-extensions',
82
transformIndexHtml: {
83
order: 'pre',
84
async handler(html) {
85
const search = '{{WORKBENCH_BUILTIN_EXTENSIONS}}';
86
if (html.indexOf(search) === -1) {
87
return html;
88
}
89
90
const extensions = await loadBuiltinExtensions();
91
const h = replaceAllOccurrences(html, search, asJSON(extensions));
92
return h;
93
}
94
}
95
};
96
}
97
98
function createHotClassSupport(): Plugin {
99
return {
100
name: 'createHotClassSupport',
101
transform: {
102
order: 'pre',
103
handler: (code, id) => {
104
if (id.endsWith('.ts')) {
105
let needsHMRAccept = false;
106
const hasCreateHotClass = code.includes('createHotClass');
107
const hasDomWidget = code.includes('DomWidget');
108
109
if (!hasCreateHotClass && !hasDomWidget) {
110
return undefined;
111
}
112
113
if (hasCreateHotClass) {
114
needsHMRAccept = true;
115
}
116
117
if (hasDomWidget) {
118
const matches = code.matchAll(/class\s+([a-zA-Z0-9_]+)\s+extends\s+DomWidget/g);
119
/// @ts-ignore
120
for (const match of matches) {
121
const className = match[1];
122
code = code + `\n${className}.registerWidgetHotReplacement(${JSON.stringify(id + '#' + className)});`;
123
needsHMRAccept = true;
124
}
125
}
126
127
if (needsHMRAccept) {
128
code = code + `\n
129
if (import.meta.hot) {
130
import.meta.hot.accept();
131
}`;
132
}
133
return code;
134
}
135
return undefined;
136
},
137
}
138
};
139
}
140
141
const logger = createLogger();
142
const loggerWarn = logger.warn;
143
144
logger.warn = (msg, options) => {
145
// amdX and the baseUrl code cannot be analyzed by vite.
146
// However, they are not needed, so it is okay to silence the warning.
147
if (msg.indexOf('vs/amdX.ts') !== -1) {
148
return;
149
}
150
if (msg.indexOf('await import(new URL(`vs/workbench/workbench.desktop.main.js`, baseUrl).href)') !== -1) {
151
return;
152
}
153
if (msg.indexOf('const result2 = await import(workbenchUrl);') !== -1) {
154
return;
155
}
156
157
// See https://github.com/microsoft/vscode/issues/278153
158
if (msg.indexOf('marked.esm.js.map') !== -1 || msg.indexOf('purify.es.mjs.map') !== -1) {
159
return;
160
}
161
162
loggerWarn(msg, options);
163
};
164
165
export default defineConfig({
166
plugins: [
167
rollupEsmUrlPlugin({}),
168
injectBuiltinExtensionsPlugin(),
169
createHotClassSupport()
170
],
171
customLogger: logger,
172
esbuild: {
173
tsconfigRaw: {
174
compilerOptions: {
175
experimentalDecorators: true,
176
}
177
}
178
},
179
root: '../..', // To support /out/... paths
180
build: {
181
rollupOptions: {
182
input: {
183
//index: path.resolve(__dirname, 'index.html'),
184
workbench: path.resolve(__dirname, 'workbench-vite.html'),
185
}
186
}
187
},
188
server: {
189
cors: true,
190
port: 5199,
191
origin: 'http://localhost:5199',
192
fs: {
193
allow: [
194
// To allow loading from sources, not needed when loading monaco-editor from npm package
195
join(import.meta.dirname, '../../../')
196
]
197
}
198
}
199
});
200
201