Skip to content

Commit 0a7becc

Browse files
fix(build): address @ionic/angular bundle size issue (#5705)
This fixes an issue where when @ionic/angular was built using Stencil and then used in an angular project it would produce much larger bundle sizes than it had previously. This issue started appearing in Stencil v4.17.x, after we switched to using esbuild for our production builds. The issue occurred because of how bundles in `internal/` were depending on code in `mock-doc/`. In particular, in `src/runtime/dom-extras.ts` we had an import from `@stencil/core/mock-doc`. In our bundles this was being correctly externalized, so that `internal/client/index.js` for instance would import from `'../../mock-doc/index.cjs'`, but the problem is that when an Angular project then tried to bundle this file later it would not tree-shake the import properly and the whole contents of mock-doc would be injected into the bundle, bloating it by 400kb or so. This is because esbuild, which `ng build` uses under the hood, does not support tree-shaking in commonjs modules. See here for details: https://esbuild.github.io/api/#tree-shaking The simplest fix for this is to add the `NODE_TYPES` enum to `src/utils/constants.ts` so that the runtime does not need to have any dependency on `mock-doc` at all.
1 parent aea6275 commit 0a7becc

File tree

7 files changed

+33
-13
lines changed

7 files changed

+33
-13
lines changed

scripts/esbuild/internal-platform-client.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { externalAlias, getBaseEsbuildOptions, getEsbuildAliases, getEsbuildExte
1717
* @param opts build options
1818
* @returns an array of ESBuild option objects
1919
*/
20-
export async function getInternalClientBundle(opts: BuildOptions): Promise<ESBuildOptions[]> {
20+
export async function getInternalClientBundles(opts: BuildOptions): Promise<ESBuildOptions[]> {
2121
const inputClientDir = join(opts.srcDir, 'client');
2222
const outputInternalClientDir = join(opts.output.internalDir, 'client');
2323
const outputInternalClientPolyfillsDir = join(outputInternalClientDir, 'polyfills');
@@ -59,9 +59,6 @@ export async function getInternalClientBundle(opts: BuildOptions): Promise<ESBui
5959
replace(createReplaceData(opts)),
6060
externalAlias('@app-data', '@stencil/core/internal/app-data'),
6161
externalAlias('@utils/shadow-css', './shadow-css.js'),
62-
// we want to get the esm, not the cjs, since we're creating an esm
63-
// bundle here
64-
externalAlias('@stencil/core/mock-doc', '../../mock-doc/index.js'),
6562
findAndReplaceLoadModule(),
6663
],
6764
};

scripts/esbuild/internal-platform-hydrate.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export async function getInternalPlatformHydrateBundles(opts: BuildOptions): Pro
3535

3636
const hydratePlatformInput = join(hydrateSrcDir, 'platform', 'index.js');
3737

38-
const external = [...getEsbuildExternalModules(opts, outputInternalHydrateDir), '@stencil/core/mock-doc'];
38+
const external = getEsbuildExternalModules(opts, outputInternalHydrateDir);
3939

4040
const internalHydrateAliases = getEsbuildAliases();
4141
internalHydrateAliases['@platform'] = hydratePlatformInput;
@@ -54,8 +54,6 @@ export async function getInternalPlatformHydrateBundles(opts: BuildOptions): Pro
5454
plugins: [
5555
externalAlias('@utils/shadow-css', '../client/shadow-css.js'),
5656
externalAlias('@app-data', '@stencil/core/internal/app-data'),
57-
// this needs to be externalized and also pointed at the esm version
58-
externalAlias('@stencil/core/mock-doc', '../../mock-doc/index.js'),
5957
],
6058
};
6159

scripts/esbuild/internal-platform-testing.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export async function getInternalTestingBundle(opts: BuildOptions): Promise<ESBu
3333
'@platform': inputTestingPlatform,
3434
};
3535

36-
const external = [...getEsbuildExternalModules(opts, opts.output.internalDir), '@stencil/core/mock-doc'];
36+
const external = getEsbuildExternalModules(opts, opts.output.internalDir);
3737

3838
const internalTestingBuildOptions: ESBuildOptions = {
3939
...getBaseEsbuildOptions(),

scripts/esbuild/internal.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { copyStencilInternalDts } from '../bundles/internal';
66
import type { BuildOptions } from '../utils/options';
77
import { writePkgJson } from '../utils/write-pkg-json';
88
import { getInternalAppDataBundles } from './internal-app-data';
9-
import { getInternalClientBundle } from './internal-platform-client';
9+
import { getInternalClientBundles } from './internal-platform-client';
1010
import { getInternalPlatformHydrateBundles } from './internal-platform-hydrate';
1111
import { getInternalTestingBundle } from './internal-platform-testing';
1212
import { getBaseEsbuildOptions, runBuilds } from './util';
@@ -53,13 +53,13 @@ export async function buildInternal(opts: BuildOptions) {
5353
platform: 'node',
5454
};
5555

56-
const clientPlatformBundle = await getInternalClientBundle(opts);
56+
const clientPlatformBundles = await getInternalClientBundles(opts);
5757
const hydratePlatformBundles = await getInternalPlatformHydrateBundles(opts);
5858
const appDataBundles = await getInternalAppDataBundles(opts);
5959
const internalTestingBundle = await getInternalTestingBundle(opts);
6060

6161
return runBuilds(
62-
[shadowCSSBundle, ...clientPlatformBundle, ...hydratePlatformBundles, internalTestingBundle, ...appDataBundles],
62+
[shadowCSSBundle, ...clientPlatformBundles, ...hydratePlatformBundles, internalTestingBundle, ...appDataBundles],
6363
opts,
6464
);
6565
}

src/runtime/dom-extras.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { BUILD } from '@app-data';
22
import { getHostRef, plt, supportsShadow } from '@platform';
3-
import { NODE_TYPES } from '@stencil/core/mock-doc';
4-
import { CMP_FLAGS, HOST_FLAGS } from '@utils';
3+
import { CMP_FLAGS, HOST_FLAGS, NODE_TYPES } from '@utils/constants';
54

65
import type * as d from '../declarations';
76
import { PLATFORM_FLAGS } from './runtime-constants';

src/utils/constants.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,28 @@ export const VALID_CONFIG_OUTPUT_TARGETS = [
231231
] as const;
232232

233233
export const GENERATED_DTS = 'components.d.ts';
234+
235+
/**
236+
* DOM Node types
237+
*
238+
* See https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
239+
*
240+
* Note: this is a duplicate of the `NODE_TYPES` enum in mock-doc, it's
241+
* copied over here so that we do not need to introduce a dependency on the
242+
* mock-doc bundle in the runtime. See
243+
* https://github.com/ionic-team/stencil/pull/5705 for more details.
244+
*/
245+
export const enum NODE_TYPES {
246+
ELEMENT_NODE = 1,
247+
ATTRIBUTE_NODE = 2,
248+
TEXT_NODE = 3,
249+
CDATA_SECTION_NODE = 4,
250+
ENTITY_REFERENCE_NODE = 5,
251+
ENTITY_NODE = 6,
252+
PROCESSING_INSTRUCTION_NODE = 7,
253+
COMMENT_NODE = 8,
254+
DOCUMENT_NODE = 9,
255+
DOCUMENT_TYPE_NODE = 10,
256+
DOCUMENT_FRAGMENT_NODE = 11,
257+
NOTATION_NODE = 12,
258+
}

tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"@stencil/core/cli": ["src/cli/index.ts"],
4141
"@sys-api-node": ["src/sys/node/index.ts"],
4242
"@utils": ["src/utils/index.ts"],
43+
"@utils/*": ["src/utils/*"],
4344
"@utils/shadow-css": ["src/utils/shadow-css"]
4445
},
4546
"pretty": true,

0 commit comments

Comments
 (0)