-
Notifications
You must be signed in to change notification settings - Fork 924
/
Copy pathesbuild.config.mjs
138 lines (124 loc) · 4.2 KB
/
esbuild.config.mjs
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
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import gzipPlugin from '@luncheon/esbuild-plugin-gzip';
import esbuild from 'esbuild';
import {copyFileSync} from 'fs';
import {createRequire} from 'node:module';
import {join} from 'path';
import tinyGlob from 'tiny-glob';
// dev mode build
const DEV = process.env.NODE_ENV === 'DEV';
// Output folder for TS files
const jsFolder = DEV ? 'lib' : 'build';
// can use glob syntax. this will create a bundle for those specific files.
// you want to add SSR'd files here so that you can hydrate them later with
// <lit-island import="js/components/element-definition.js"></lit-island>
const tsEntrypoints = [
// entrypoints for hydrating lit-islands
'./src/hydration-entrypoints/**/*.ts',
// also include a bundle for each individual page
'./src/pages/*.ts',
// SSR stuff
'./src/ssr-utils/lit-hydrate-support.ts',
'./src/ssr-utils/lit-island.ts',
];
const filesPromises = tsEntrypoints.map(async (entry) => tinyGlob(entry));
const entryPoints = (await Promise.all(filesPromises)).flat();
// Shared esbuild config values
let config = {
bundle: true,
outdir: jsFolder,
minify: false,
format: 'esm',
treeShaking: true,
write: true,
sourcemap: true,
splitting: true,
};
let componentsBuild = Promise.resolve();
// development build
if (DEV) {
componentsBuild = esbuild
.build({
...config,
entryPoints,
})
.catch(() => process.exit(1));
// production build
} else {
// config must be same for SSR and client builds to prevent hydration template
// mismatches because we minify the templates in prod
config = {
bundle: true,
outdir: jsFolder,
minify: true,
format: 'esm',
treeShaking: true,
legalComments: 'external',
plugins: [
// This plugin currently breaks certain css props for SVGs
// (circularprogress) minifyHTMLLiteralsPlugin({
// shouldMinify: (template) => {
// const tag = template.tag && template.tag.toLowerCase();
// return (
// !!tag &&
// (tag.includes('html') || tag.includes('svg')) &&
// // tag name interpolations break
// tag !== 'statichtml'
// );
// },
// }),
gzipPlugin({
gzip: true,
}),
],
// Needs to be off per the gzipPlugin docs
write: false,
splitting: true,
};
componentsBuild = esbuild
.build({
...config,
entryPoints,
})
.catch(() => process.exit(1));
}
// seperate build so that the SSR bundle doesn't affect bundling for the
// frontend
const ssrBuild = esbuild
.build({
...config,
format: 'iife',
splitting: false,
conditions: ['node'],
entryPoints: ['src/ssr.ts'],
})
.catch(() => process.exit(1));
// Glob of files that will be inlined on the page in <script> tags
const tsInlineEntrypoints = [
'./src/ssr-utils/dsd-polyfill.ts',
// Anything in this directory will be inlined
'./src/inline/*.ts',
];
const inlineFilesPromises =
tsInlineEntrypoints.map(async (entry) => tinyGlob(entry));
const inlineEntryPoints = (await Promise.all(inlineFilesPromises)).flat();
// this code is inlined into the HTML because it is performance-sensitive
const inlineBuild = esbuild
.build({
...config,
format: 'iife',
splitting: false,
entryPoints: inlineEntryPoints,
})
.catch(() => process.exit(1));
await Promise.all([componentsBuild, ssrBuild, inlineBuild]);
// Copy the playground-elements worker to the build folder
const require = createRequire(import.meta.url);
copyFileSync(
require.resolve('playground-elements/playground-typescript-worker.js'),
join(jsFolder, 'hydration-entrypoints/playground-typescript-worker.js'));
process.exit(0);