Skip to content

Commit

Permalink
feat(webpack): enable babel cache to make rebuild faster
Browse files Browse the repository at this point in the history
  • Loading branch information
chenjiahan committed Sep 27, 2022
1 parent d3795e8 commit 0a524d1
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 32 deletions.
5 changes: 5 additions & 0 deletions .changeset/sour-lamps-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@modern-js/webpack': patch
---

feat(webpack): enable babel cache to make rebuild faster
12 changes: 7 additions & 5 deletions packages/cli/webpack/src/config/features/babel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export function applyScriptCondition({
}

export function applyBabelLoader({
chain,
config,
loaders,
appContext,
Expand All @@ -90,13 +91,14 @@ export function applyBabelLoader({
useTsLoader: boolean;
babelPresetAppOptions?: Partial<BabelPresetAppOptions>;
}) {
const { options, includes, excludes } = getBabelOptions(
appContext.metaName,
appContext.appDirectory,
const { options, includes, excludes } = getBabelOptions({
name: chain.get('name'),
chain: createBabelChain(),
config,
createBabelChain(),
metaName: appContext.metaName,
appDirectory: appContext.appDirectory,
babelPresetAppOptions,
);
});

const rule = loaders
.oneOf(CHAIN_ID.ONE_OF.JS)
Expand Down
102 changes: 82 additions & 20 deletions packages/cli/webpack/src/utils/getBabelOptions.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import path from 'path';
import { isProd, applyOptionsChain, isUseSSRBundle } from '@modern-js/utils';
import {
getBabelConfig,
BabelChain,
Options as BabelPresetAppOptions,
} from '@modern-js/babel-preset-app';
import type { NormalizedConfig, TransformOptions } from '@modern-js/core';
import { CACHE_DIRECTORY } from './constants';

export const getUseBuiltIns = (config: NormalizedConfig) => {
const { polyfill } = config.output || {};
Expand All @@ -14,13 +16,57 @@ export const getUseBuiltIns = (config: NormalizedConfig) => {
return polyfill;
};

export const getBabelOptions = (
metaName: string,
appDirectory: string,
config: NormalizedConfig,
chain: BabelChain,
babelPresetAppOptions?: Partial<BabelPresetAppOptions>,
) => {
function getCacheIdentifier(babelConfig: TransformOptions) {
let cacheIdentifier = process.env.NODE_ENV;

const packages = [
{
name: 'babel-loader',
version: require('../../compiled/babel-loader/package.json').version,
},
{
name: '@modern-js/babel-preset-app',
version:
require('../../package.json').dependencies[
'@modern-js/babel-preset-app'
],
},
];

for (const { name, version } of packages) {
cacheIdentifier += `:${name}@${version}`;
}

const pluginItems = [
...(babelConfig.presets || []),
...(babelConfig.plugins || []),
];
pluginItems.forEach(pluginItem => {
if (Array.isArray(pluginItem)) {
cacheIdentifier += `:${pluginItem[0]}`;
} else {
cacheIdentifier += `:${pluginItem}`;
}
});

return cacheIdentifier;
}

export const getBabelOptions = ({
name,
chain,
config,
metaName,
appDirectory,
babelPresetAppOptions,
}: {
name: string;
chain: BabelChain;
config: NormalizedConfig;
metaName: string;
appDirectory: string;
babelPresetAppOptions?: Partial<BabelPresetAppOptions>;
}) => {
const lodashOptions = applyOptionsChain(
{ id: ['lodash', 'ramda'] },
config.tools?.lodash as any,
Expand Down Expand Up @@ -56,26 +102,42 @@ export const getBabelOptions = (
},
};

const babelOptions: TransformOptions = {
const babelConfig = getBabelConfig({
metaName,
appDirectory,
lodash: lodashOptions,
useLegacyDecorators: !config.output?.enableLatestDecorators,
useBuiltIns: getUseBuiltIns(config),
chain,
styledComponents: styledComponentsOptions,
userBabelConfig: config.tools?.babel,
userBabelConfigUtils: babelUtils,
...babelPresetAppOptions,
});

const babelLoaderOptions: TransformOptions & {
cacheIdentifier?: string;
cacheDirectory?: string;
cacheCompression?: boolean;
} = {
babelrc: false,
configFile: false,
compact: isProd(),
...getBabelConfig({
metaName,
// enable babel loader cache because:
// 1. babel-loader cache can speed up the rebuild time (tested on large projects).
// 2. webpack cache get invalid in many cases, such as config changed, while babel cache is still valid.
cacheIdentifier: getCacheIdentifier(babelConfig),
cacheDirectory: path.resolve(
appDirectory,
lodash: lodashOptions,
useLegacyDecorators: !config.output?.enableLatestDecorators,
useBuiltIns: getUseBuiltIns(config),
chain,
styledComponents: styledComponentsOptions,
userBabelConfig: config.tools?.babel,
userBabelConfigUtils: babelUtils,
...babelPresetAppOptions,
}),
CACHE_DIRECTORY,
`babel/${name}`,
),
cacheCompression: false,
...babelConfig,
};

return {
options: babelOptions,
options: babelLoaderOptions,
includes,
excludes,
};
Expand Down
3 changes: 3 additions & 0 deletions packages/cli/webpack/tests/__snapshots__/utils.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
exports[`getBabelOptions should return babel options as expected 1`] = `
Object {
"babelrc": false,
"cacheCompression": false,
"cacheDirectory": /.cache/babel/client,
"cacheIdentifier": /cli/babel-preset-base/compiled/babel-plugin-styled-components/index.js,
"compact": false,
"configFile": false,
"plugins": Array [
Expand Down
15 changes: 8 additions & 7 deletions packages/cli/webpack/tests/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,16 @@ describe('mergeRegex', () => {

describe('getBabelOptions', () => {
it('should return babel options as expected', () => {
const { options: babelOptions } = getBabelOptions(
'metaName',
'/root',
{} as any,
createBabelChain(),
{
const { options: babelOptions } = getBabelOptions({
name: 'client',
metaName: 'metaName',
appDirectory: '/root',
config: {} as any,
chain: createBabelChain(),
babelPresetAppOptions: {
target: 'client',
},
);
});

setPathSerializer();
expect(babelOptions).toMatchSnapshot();
Expand Down

0 comments on commit 0a524d1

Please sign in to comment.