Skip to content

Commit fa1a6af

Browse files
authored
Use ES modules and dynamic import for Webpack latest builds (home-assistant#16849)
1 parent 197638b commit fa1a6af

File tree

8 files changed

+47
-22
lines changed

8 files changed

+47
-22
lines changed

.browserslistrc

+6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ supports es6-module-dynamic-import
1010
not Safari < 13
1111
not iOS < 13
1212

13+
# Exclude KaiOS, QQ, and UC browsers due to lack of sufficient feature support data
14+
# Babel ignores these automatically, but we need here for Webpack to output ESM with dynamic imports
15+
not KaiOS > 0
16+
not QQAndroid > 0
17+
not UCAndroid > 0
18+
1319
# Exclude unsupported browsers
1420
not dead
1521

build-scripts/bundle.cjs

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ module.exports.htmlMinifierOptions = {
7777
module.exports.terserOptions = ({ latestBuild, isTestBuild }) => ({
7878
safari10: !latestBuild,
7979
ecma: latestBuild ? 2015 : 5,
80+
module: latestBuild,
8081
format: { comments: false },
8182
sourceMap: !isTestBuild,
8283
});

build-scripts/webpack.cjs

+10-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const createWebpackConfig = ({
4141
return {
4242
name,
4343
mode: isProdBuild ? "production" : "development",
44-
target: ["web", latestBuild ? "es2017" : "es5"],
44+
target: `browserslist:${latestBuild ? "modern" : "legacy"}`,
4545
// For tests/CI, source maps are skipped to gain build speed
4646
// For production, generate source maps for accurate stack traces without source code
4747
// For development, generate "cheap" versions that can map to original line numbers
@@ -84,6 +84,13 @@ const createWebpackConfig = ({
8484
],
8585
moduleIds: isProdBuild && !isStatsBuild ? "deterministic" : "named",
8686
chunkIds: isProdBuild && !isStatsBuild ? "deterministic" : "named",
87+
splitChunks: {
88+
// Disable splitting for web workers with ESM output
89+
// Imports of external chunks are broken
90+
chunks: latestBuild
91+
? (chunk) => !chunk.canBeInitial() && !/^.+-worker$/.test(chunk.name)
92+
: undefined,
93+
},
8794
},
8895
plugins: [
8996
!isStatsBuild && new WebpackBar({ fancy: !isProdBuild }),
@@ -163,6 +170,7 @@ const createWebpackConfig = ({
163170
},
164171
},
165172
output: {
173+
module: latestBuild,
166174
filename: ({ chunk }) =>
167175
!isProdBuild || isStatsBuild || dontHash.has(chunk.name)
168176
? "[name].js"
@@ -196,7 +204,7 @@ const createWebpackConfig = ({
196204
: undefined,
197205
},
198206
experiments: {
199-
topLevelAwait: true,
207+
outputModule: true,
200208
},
201209
};
202210
};
+17-16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Remote, wrap } from "comlink";
2-
import type { Api } from "./sort_filter_worker";
2+
import type { Api } from "./sort-filter-worker";
33

44
type FilterDataType = Api["filterData"];
55
type FilterDataParamTypes = Parameters<FilterDataType>;
@@ -9,27 +9,28 @@ type SortDataParamTypes = Parameters<SortDataType>;
99

1010
let worker: Remote<Api> | undefined;
1111

12-
export const filterData = (
13-
data: FilterDataParamTypes[0],
14-
columns: FilterDataParamTypes[1],
15-
filter: FilterDataParamTypes[2]
16-
): Promise<ReturnType<FilterDataType>> => {
12+
const getWorker = () => {
1713
if (!worker) {
18-
worker = wrap(new Worker(new URL("./sort_filter_worker", import.meta.url)));
14+
worker = wrap(
15+
new Worker(
16+
/* webpackChunkName: "sort-filter-worker" */
17+
new URL("./sort-filter-worker", import.meta.url)
18+
)
19+
);
1920
}
20-
21-
return worker.filterData(data, columns, filter);
21+
return worker;
2222
};
2323

24+
export const filterData = (
25+
data: FilterDataParamTypes[0],
26+
columns: FilterDataParamTypes[1],
27+
filter: FilterDataParamTypes[2]
28+
): Promise<ReturnType<FilterDataType>> =>
29+
getWorker().filterData(data, columns, filter);
2430
export const sortData = (
2531
data: SortDataParamTypes[0],
2632
columns: SortDataParamTypes[1],
2733
direction: SortDataParamTypes[2],
2834
sortColumn: SortDataParamTypes[3]
29-
): Promise<ReturnType<SortDataType>> => {
30-
if (!worker) {
31-
worker = wrap(new Worker(new URL("./sort_filter_worker", import.meta.url)));
32-
}
33-
34-
return worker.sortData(data, columns, direction, sortColumn);
35-
};
35+
): Promise<ReturnType<SortDataType>> =>
36+
getWorker().sortData(data, columns, direction, sortColumn);
File renamed without changes.

src/resources/render-markdown.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Remote, wrap } from "comlink";
2-
import type { Api } from "./markdown_worker";
2+
import type { Api } from "./markdown-worker";
33

44
type RenderMarkdownType = Api["renderMarkdown"];
55
type RenderMarkdownParamTypes = Parameters<RenderMarkdownType>;
@@ -12,8 +12,12 @@ export const renderMarkdown = async (
1212
hassOptions?: RenderMarkdownParamTypes[2]
1313
): Promise<ReturnType<RenderMarkdownType>> => {
1414
if (!worker) {
15-
worker = wrap(new Worker(new URL("./markdown_worker", import.meta.url)));
15+
worker = wrap(
16+
new Worker(
17+
/* webpackChunkName: "markdown-worker" */
18+
new URL("./markdown-worker", import.meta.url)
19+
)
20+
);
1621
}
17-
1822
return worker.renderMarkdown(content, markedOptions, hassOptions);
1923
};

test/webpack.config.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import webpack from "../build-scripts/webpack.cjs";
22

3-
export default webpack.createAppConfig({
3+
const config = webpack.createAppConfig({
44
isProdBuild: false,
55
latestBuild: true,
66
isStatsBuild: false,
77
isTestBuild: true,
88
});
9+
10+
// instant-mocha forces a CJS library, so cannot output ESM
11+
config.output.module = false;
12+
13+
export default config;

0 commit comments

Comments
 (0)