Skip to content
This repository has been archived by the owner on May 15, 2024. It is now read-only.

feat(styles-loader): disable purgecss by default #614

Merged
merged 8 commits into from
Mar 11, 2024
33 changes: 16 additions & 17 deletions packages/one-app-bundler/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,22 @@ You can pass only one if you wish to customize a single build target.

#### [`purgecss`](https://github.com/FullHuman/purgecss) Options

`purgecss` is an opt-in optimization that can reduce the overall bundle size of your module by
eliminating unused css from your module's bundle. You can enable `purgecss` by setting
`bundler.purgecss.disabled` to `false` in the `one-amex` key in your module's `package.json`:

```json
{
"one-amex": {
"bundler": {
"purgecss": {
"disabled": false
code-forger marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
}
```

You may add additional paths for `purgecss` to consider before stripping out
unused CSS by adding an array of glob patterns to `bundler.purgecss.paths`
under `bundler.purgecss.paths`. The example below illustrates how we would add
Expand Down Expand Up @@ -353,23 +369,6 @@ before enabling any of the following:
}
```

##### Disabling purgecss

`purgecss` can be disabled for your module by adding
`bundler.purgecss.disabled` as `true`. **Disabling purgecss entirely may increase your module bundle size and decrease performance.**

```json
{
"one-amex": {
"bundler": {
"purgecss": {
"disabled": true
}
}
}
}
```

#### Legacy browser support

`disableDevelopmentLegacyBundle` can be added to your bundler config and set to *true* to opt out of bundling the `legacy` assets. This will reduce bundle size and build times. This is only configured to be removed when in `development`. `production` builds will not skip the `legacy` build.
Expand Down
1 change: 0 additions & 1 deletion packages/one-app-bundler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
"dependencies": {
"@americanexpress/one-app-dev-bundler": "^1.7.0",
"@americanexpress/one-app-locale-bundler": "^6.6.0",
"@americanexpress/purgecss-loader": "4.0.0",
code-forger marked this conversation as resolved.
Show resolved Hide resolved
"@babel/core": "^7.22.20",
"ajv": "^8.12.0",
"assert": "^2.1.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,158 @@ describe('Esbuild plugin stylesLoader', () => {
describe('NON-PRODUCTION environment', () => {
mockNodeEnv('development');

it('should transform inputs to default outputs for purged css, browser', async () => {
glob.sync.mockReturnValue(['Test.jsx']);

getModulesBundlerConfig.mockImplementationOnce(() => ({
disabled: false,
}));

expect.assertions(3);

const plugin = stylesLoader({}, {
bundleType: BUNDLE_TYPES.BROWSER,
});
const onLoadHook = runSetupAndGetLifeHooks(plugin).onLoad[0].hookFunction;
const additionalMockedFiles = {
'Test.jsx': `\
import styles from './index.module.css';

const Component = () => {
return (
<div className={styles.root}>
<p className={styles.second}>Testing</p>
</div>
);
}

export default Component`,
};

const {
contents, loader,
} = await runOnLoadHook(
onLoadHook,
{
mockFileNAme: 'index.module.css',
mockFileContent: `\
.root {
background: white;
}

.somethingElse {
font-color: lime;
}

.second {
font-color: black;
}`,
},
additionalMockedFiles
);

expect(sassCompile).toHaveBeenCalledTimes(0);
expect(loader).toEqual('js');
expect(contents).toMatchInlineSnapshot(`
"const digest = 'be76540996d2256b09af85f09bb93016999ae115235d972319628c011a06d6cc';
const css = \` ._root_w8zvp_1 {
background: white;
}

._second_w8zvp_9 {
font-color: black;
}\`;
(function() {
if ( global.BROWSER && !document.getElementById(digest)) {
var el = document.createElement('style');
el.id = digest;
el.textContent = css;
document.head.appendChild(el);
}
})();
export const root = '_root_w8zvp_1';
export const second = '_second_w8zvp_9';
export default { root, second };
export { css, digest };"
`);
});

it('should transform inputs to named outputs for purged css, browser', async () => {
glob.sync.mockReturnValue(['Test.jsx']);

getModulesBundlerConfig.mockImplementationOnce(() => ({
disabled: false,
}));

expect.assertions(3);

const plugin = stylesLoader({}, {
bundleType: BUNDLE_TYPES.BROWSER,
});
const onLoadHook = runSetupAndGetLifeHooks(plugin).onLoad[0].hookFunction;
const additionalMockedFiles = {
'Test.jsx': `\
import { root, second } from './index.module.css';

const Component = () => {
return (
<div className={root}>
<p className={second}>Testing</p>
</div>
);
}

export default Component`,
};

const {
contents, loader,
} = await runOnLoadHook(
onLoadHook,
{
mockFileNAme: 'index.module.css',
mockFileContent: `\
.root {
background: white;
}

.somethingElse {
font-color: lime;
}

.second {
font-color: black;
}`,
},
additionalMockedFiles
);

expect(sassCompile).toHaveBeenCalledTimes(0);
expect(loader).toEqual('js');
expect(contents).toMatchInlineSnapshot(`
"const digest = 'be76540996d2256b09af85f09bb93016999ae115235d972319628c011a06d6cc';
const css = \` ._root_w8zvp_1 {
background: white;
}

._second_w8zvp_9 {
font-color: black;
}\`;
(function() {
if ( global.BROWSER && !document.getElementById(digest)) {
var el = document.createElement('style');
el.id = digest;
el.textContent = css;
document.head.appendChild(el);
}
})();
export const root = '_root_w8zvp_1';
export const second = '_second_w8zvp_9';
export default { root, second };
export { css, digest };"
`);
});

it('should transform inputs to outputs for scss, in the browser', async () => {
expect.assertions(4);

Expand Down Expand Up @@ -518,6 +670,10 @@ export { css, digest };"
it('should transform inputs to default outputs for purged css, browser', async () => {
glob.sync.mockReturnValue(['Test.jsx']);

getModulesBundlerConfig.mockImplementationOnce(() => ({
disabled: false,
}));

expect.assertions(3);

const plugin = stylesLoader({}, {
Expand Down Expand Up @@ -590,6 +746,10 @@ export { css, digest };"
it('should transform inputs to named outputs for purged css, browser', async () => {
glob.sync.mockReturnValue(['Test.jsx']);

getModulesBundlerConfig.mockImplementationOnce(() => ({
disabled: false,
}));

expect.assertions(3);

const plugin = stylesLoader({}, {
Expand Down Expand Up @@ -659,13 +819,9 @@ export { css, digest };"
`);
});

it('should transform inputs to outputs for scss, with purge disabled, in the browser', async () => {
it('should transform inputs to outputs for scss, in the browser', async () => {
expect.assertions(4);

getModulesBundlerConfig.mockImplementation(() => ({
disabled: true,
}));

const mockFileName = 'index.scss';
const mockFileContent = `body {
background: white;
Expand Down Expand Up @@ -711,13 +867,9 @@ export { css, digest };"
`);
});

it('should transform inputs to outputs for css, with purge disabled, in the browser', async () => {
it('should transform inputs to outputs for css, in the browser', async () => {
expect.assertions(3);

getModulesBundlerConfig.mockImplementation(() => ({
disabled: true,
}));

const mockFileName = 'index.css';
const mockFileContent = `body {
background: white;
Expand Down
3 changes: 2 additions & 1 deletion packages/one-app-dev-bundler/esbuild/utils/load-styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ const loadStyles = async ({
let cssModulesJSON = {};
const purgecssConfig = getModulesBundlerConfig('purgecss') || {};
const result = await postcss([
(process.env.NODE_ENV === 'production' && !purgecssConfig.disabled) && purgecss(purgecssConfig),
// purgecss will not execute unless `disabled is set to `false` (opt-in by default)
purgecssConfig.disabled === false && purgecss(purgecssConfig),
code-forger marked this conversation as resolved.
Show resolved Hide resolved
cssModules({
localsConvention,
generateScopedName,
Expand Down
28 changes: 5 additions & 23 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,6 @@
prop-types "^15.5.6"
warning "^3.0.0"

"@americanexpress/[email protected]":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@americanexpress/purgecss-loader/-/purgecss-loader-4.0.0.tgz#71d87b3d7861b5c9128a3e3aff4d882710129d79"
integrity sha512-PO8swpaOZf28j9r44NLaChOmmV23VUAbrMT9FeB11U+0YtZNL74uwC3HxHejtKP2VP7+dty3tmIKy3ysUt8mkA==
dependencies:
loader-utils "^1.4.2"
purgecss "^4.1.3"

"@americanexpress/vitruvius@^2.0.0":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@americanexpress/vitruvius/-/vitruvius-2.0.2.tgz#7325ba00e3c57b0993973787ae50b0f7c72c3c38"
Expand Down Expand Up @@ -4733,7 +4725,7 @@ commander@^7.2.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==

commander@^8.0.0, commander@^8.3.0:
commander@^8.3.0:
version "8.3.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
Expand Down Expand Up @@ -7319,7 +7311,7 @@ glob@^10.3.4, glob@^10.3.7:
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
path-scurry "^1.10.1"

glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7, glob@^7.2.3:
glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.3:
version "7.2.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
Expand Down Expand Up @@ -9237,7 +9229,7 @@ loader-runner@^4.2.0:
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1"
integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==

loader-utils@^1.2.3, loader-utils@^1.4.2:
loader-utils@^1.2.3:
version "1.4.2"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3"
integrity sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==
Expand Down Expand Up @@ -11189,7 +11181,7 @@ postcss-reduce-transforms@^6.0.1:
dependencies:
postcss-value-parser "^4.2.0"

postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.0.15, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.6:
postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.0.15, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4:
version "6.0.15"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz#11cc2b21eebc0b99ea374ffb9887174855a01535"
integrity sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==
Expand Down Expand Up @@ -11225,7 +11217,7 @@ postcss@^7.0.14, postcss@^7.0.23, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.
picocolors "^0.2.1"
source-map "^0.6.1"

postcss@^8.2.1, postcss@^8.3.5, postcss@^8.4.21, postcss@^8.4.33:
postcss@^8.2.1, postcss@^8.4.21, postcss@^8.4.33:
version "8.4.33"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.33.tgz#1378e859c9f69bf6f638b990a0212f43e2aaa742"
integrity sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==
Expand Down Expand Up @@ -11413,16 +11405,6 @@ purgecss@^3.1.3:
postcss "^8.2.1"
postcss-selector-parser "^6.0.2"

purgecss@^4.1.3:
version "4.1.3"
resolved "https://registry.yarnpkg.com/purgecss/-/purgecss-4.1.3.tgz#683f6a133c8c4de7aa82fe2746d1393b214918f7"
integrity sha512-99cKy4s+VZoXnPxaoM23e5ABcP851nC2y2GROkkjS8eJaJtlciGavd7iYAw2V84WeBqggZ12l8ef44G99HmTaw==
dependencies:
commander "^8.0.0"
glob "^7.1.7"
postcss "^8.3.5"
postcss-selector-parser "^6.0.6"

q@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
Expand Down
Loading