fix(nextjs): update babel setup to better support next apps (#4944)
* fix(nextjs): update babel setup to better support next apps * fix(testing): remove babel-jest.config.json used in jest.config.js - Fix `@nrwl/web/babel` to support Jest as well
This commit is contained in:
parent
372b7939c6
commit
ddec362a5a
@ -90,6 +90,14 @@ Type: `boolean`
|
||||
|
||||
Use pascal case file names.
|
||||
|
||||
### skipBabelrc
|
||||
|
||||
Default: `false`
|
||||
|
||||
Type: `boolean`
|
||||
|
||||
Do not generate .babelrc file. Useful for Node libraries that are not compiled by Babel
|
||||
|
||||
### skipFormat
|
||||
|
||||
Default: `false`
|
||||
|
||||
@ -90,6 +90,14 @@ Type: `boolean`
|
||||
|
||||
Use pascal case file names.
|
||||
|
||||
### skipBabelrc
|
||||
|
||||
Default: `false`
|
||||
|
||||
Type: `boolean`
|
||||
|
||||
Do not generate .babelrc file. Useful for Node libraries that are not compiled by Babel
|
||||
|
||||
### skipFormat
|
||||
|
||||
Default: `false`
|
||||
|
||||
@ -90,6 +90,14 @@ Type: `boolean`
|
||||
|
||||
Use pascal case file names.
|
||||
|
||||
### skipBabelrc
|
||||
|
||||
Default: `false`
|
||||
|
||||
Type: `boolean`
|
||||
|
||||
Do not generate .babelrc file. Useful for Node libraries that are not compiled by Babel
|
||||
|
||||
### skipFormat
|
||||
|
||||
Default: `false`
|
||||
|
||||
@ -4,6 +4,9 @@
|
||||
module.exports = function (api, options) {
|
||||
api.assertVersion(7);
|
||||
return {
|
||||
presets: [[require.resolve('babel-preset-gatsby'), { useBuiltIns: true }]],
|
||||
presets: [
|
||||
'@nrwl/web/babel',
|
||||
[require.resolve('babel-preset-gatsby'), { useBuiltIns: true }],
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
@ -181,13 +181,7 @@ describe('app', () => {
|
||||
.read('apps/my-app/src/pages/index.tsx')
|
||||
.toString();
|
||||
|
||||
const babelJestConfig = readJson(
|
||||
tree,
|
||||
'apps/my-app/babel-jest.config.json'
|
||||
);
|
||||
|
||||
expect(indexContent).toMatch(/<style jsx>/);
|
||||
expect(babelJestConfig.plugins).toContain('styled-jsx/babel');
|
||||
expect(
|
||||
tree.exists('apps/my-app/src/pages/index.module.styled-jsx')
|
||||
).toBeFalsy();
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`jestProject --babelJest should generate proper jest.transform and babel-jest.config.json when babelJest and supportTsx is true 1`] = `
|
||||
exports[`jestProject --babelJest should generate proper jest.transform when babelJest and supportTsx is true 1`] = `
|
||||
"module.exports = {
|
||||
displayName: 'lib1',
|
||||
preset: '../../jest.preset.js',
|
||||
transform: {
|
||||
'^.+\\\\\\\\.[tj]sx?$': [ 'babel-jest',
|
||||
{ cwd: __dirname, configFile: './babel-jest.config.json' }]
|
||||
'^.+\\\\\\\\.[tj]sx?$': 'babel-jest'
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||
coverageDirectory: '../../coverage/libs/lib1'
|
||||
@ -14,13 +13,12 @@ exports[`jestProject --babelJest should generate proper jest.transform and babel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`jestProject --babelJest should generate proper jest.transform and babel-jest.config.json when babelJest is true 1`] = `
|
||||
exports[`jestProject --babelJest should generate proper jest.transform when babelJest is true 1`] = `
|
||||
"module.exports = {
|
||||
displayName: 'lib1',
|
||||
preset: '../../jest.preset.js',
|
||||
transform: {
|
||||
'^.+\\\\\\\\.[tj]s$': [ 'babel-jest',
|
||||
{ cwd: __dirname, configFile: './babel-jest.config.json' }]
|
||||
'^.+\\\\\\\\.[tj]s$': 'babel-jest'
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'js', 'html'],
|
||||
coverageDirectory: '../../coverage/libs/lib1'
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"targets": {
|
||||
"node": "current"
|
||||
}
|
||||
}
|
||||
],
|
||||
"@babel/preset-typescript"<% if (supportTsx) { %>,
|
||||
"@babel/preset-react"<% } %>
|
||||
]
|
||||
}
|
||||
@ -16,8 +16,7 @@ module.exports = {
|
||||
},<% } %><% if(testEnvironment) { %>
|
||||
testEnvironment: '<%= testEnvironment %>',<% } %><% if(skipSerializers){ %>
|
||||
transform: {
|
||||
<% if (supportTsx){ %>'^.+\\.[tj]sx?$'<% } else { %>'^.+\\.[tj]s$'<% } %>: <% if (transformer == 'babel-jest') { %>[ 'babel-jest',
|
||||
{ cwd: __dirname, configFile: './babel-jest.config.json' }]<% } else { %> 'ts-jest' <% } %>
|
||||
<% if (supportTsx){ %>'^.+\\.[tj]sx?$'<% } else { %>'^.+\\.[tj]s$'<% } %>: <% if (transformer == 'babel-jest') { %>'babel-jest'<% } else { %> 'ts-jest' <% } %>
|
||||
},<% if (supportTsx) { %>
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],<% } else { %>
|
||||
moduleFileExtensions: ['ts', 'js', 'html'],<% } %><% } %>
|
||||
|
||||
@ -275,7 +275,7 @@ describe('jestProject', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate proper jest.transform and babel-jest.config.json when babelJest is true', async () => {
|
||||
it('should generate proper jest.transform when babelJest is true', async () => {
|
||||
await jestProjectGenerator(tree, {
|
||||
...defaultOptions,
|
||||
project: 'lib1',
|
||||
@ -291,27 +291,9 @@ describe('jestProject', () => {
|
||||
expect(
|
||||
tree.read('libs/lib1/jest.config.js').toString()
|
||||
).toMatchSnapshot();
|
||||
|
||||
expect(tree.exists('libs/lib1/babel-jest.config.json'));
|
||||
expect(readJson(tree, 'libs/lib1/babel-jest.config.json'))
|
||||
.toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"presets": Array [
|
||||
Array [
|
||||
"@babel/preset-env",
|
||||
Object {
|
||||
"targets": Object {
|
||||
"node": "current",
|
||||
},
|
||||
},
|
||||
],
|
||||
"@babel/preset-typescript",
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should generate proper jest.transform and babel-jest.config.json when babelJest and supportTsx is true', async () => {
|
||||
it('should generate proper jest.transform when babelJest and supportTsx is true', async () => {
|
||||
await jestProjectGenerator(tree, {
|
||||
...defaultOptions,
|
||||
project: 'lib1',
|
||||
@ -321,24 +303,6 @@ describe('jestProject', () => {
|
||||
expect(
|
||||
tree.read('libs/lib1/jest.config.js').toString()
|
||||
).toMatchSnapshot();
|
||||
|
||||
expect(readJson(tree, 'libs/lib1/babel-jest.config.json'))
|
||||
.toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"presets": Array [
|
||||
Array [
|
||||
"@babel/preset-env",
|
||||
Object {
|
||||
"targets": Object {
|
||||
"node": "current",
|
||||
},
|
||||
},
|
||||
],
|
||||
"@babel/preset-typescript",
|
||||
"@babel/preset-react",
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -21,8 +21,4 @@ export function createFiles(tree: Tree, options: JestProjectSchema) {
|
||||
if (options.setupFile === 'none') {
|
||||
tree.delete(join(projectConfig.root, './src/test-setup.ts'));
|
||||
}
|
||||
|
||||
if (!options.babelJest) {
|
||||
tree.delete(join(projectConfig.root, './babel-jest.config.json'));
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import { serializeJson } from '@nrwl/workspace';
|
||||
import { jestConfigObject } from '../utils/config/legacy/functions';
|
||||
|
||||
import { getJestObject } from './require-jest-config';
|
||||
|
||||
jest.mock('./require-jest-config');
|
||||
const getJestObjectMock = getJestObject as jest.Mock<typeof getJestObject>;
|
||||
|
||||
@ -28,10 +29,7 @@ const reactJestObject = {
|
||||
preset: '../../jest.config.js',
|
||||
transform: {
|
||||
'^(?!.*\\\\.(js|jsx|ts|tsx|css|json)$)': '@nrwl/react/plugins/jest',
|
||||
'^.+\\\\.[tj]sx?$': [
|
||||
'babel-jest',
|
||||
{ cwd: __dirname, configFile: './babel-jest.config.json' },
|
||||
],
|
||||
'^.+\\\\.[tj]sx?$': ['babel-jest', { cwd: __dirname }],
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
coverageDirectory: '../../coverage/apps/my-react-app',
|
||||
|
||||
10
packages/next/babel.ts
Normal file
10
packages/next/babel.ts
Normal file
@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Babel preset to provide Next.js support for Nx.
|
||||
*/
|
||||
module.exports = function (api, options) {
|
||||
api.assertVersion(7);
|
||||
return {
|
||||
presets: ['next/babel'],
|
||||
plugins: [['@babel/plugin-proposal-decorators', { legacy: true }]],
|
||||
};
|
||||
};
|
||||
@ -24,6 +24,12 @@
|
||||
"version": "11.0.0-beta.0",
|
||||
"description": "Update libraries",
|
||||
"factory": "./src/migrations/update-11-0-0/update-11-0-0"
|
||||
},
|
||||
"update-babel-config-11.5.0": {
|
||||
"cli": "nx",
|
||||
"version": "11.5.0-beta.1",
|
||||
"description": "Update .babelrc to use '@nrwl/next/babel' instead of 'next/babel'",
|
||||
"factory": "./src/migrations/update-11-5-0/update-babel-config"
|
||||
}
|
||||
},
|
||||
"packageJsonUpdates": {
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
"next": "^10.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-proposal-decorators": "^7.8.3",
|
||||
"@nrwl/react": "*",
|
||||
"@nrwl/cypress": "*",
|
||||
"@nrwl/jest": "*",
|
||||
|
||||
@ -28,12 +28,19 @@ function withNx(nextConfig = {} as any) {
|
||||
const userWebpack = nextConfig.webpack || ((x) => x);
|
||||
return {
|
||||
...nextConfig,
|
||||
/*
|
||||
* Modify the Next.js webpack config to allow workspace libs to use css modules.
|
||||
*
|
||||
* Note: This would be easier if Next.js exposes css-loader and sass-loader on `defaultLoaders`.
|
||||
*/
|
||||
webpack: (config, options) => {
|
||||
/*
|
||||
* Update babel to support our monorepo setup.
|
||||
* The 'upward' mode allows the root babel.config.json and per-project .babelrc files to be picked up.
|
||||
*/
|
||||
options.defaultLoaders.babel.options.babelrc = true;
|
||||
options.defaultLoaders.babel.options.rootMode = 'upward';
|
||||
|
||||
/*
|
||||
* Modify the Next.js webpack config to allow workspace libs to use css modules.
|
||||
* Note: This would be easier if Next.js exposes css-loader and sass-loader on `defaultLoaders`.
|
||||
*/
|
||||
|
||||
// Include workspace libs in css/sass loaders
|
||||
const includes = [join(appRootPath, workspaceLayout().libsDir)];
|
||||
|
||||
|
||||
@ -150,13 +150,7 @@ describe('app', () => {
|
||||
|
||||
const indexContent = tree.read('apps/my-app/pages/index.tsx').toString();
|
||||
|
||||
const babelJestConfig = readJson(
|
||||
tree,
|
||||
'apps/my-app/babel-jest.config.json'
|
||||
);
|
||||
|
||||
expect(indexContent).toMatch(/<style jsx>{`.page {}`}<\/style>/);
|
||||
expect(babelJestConfig.plugins).toContain('styled-jsx/babel');
|
||||
expect(
|
||||
tree.exists('apps/my-app/pages/index.module.styled-jsx')
|
||||
).toBeFalsy();
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
{
|
||||
"presets": ["next/babel"],
|
||||
"plugins": [<% if (style === 'styled-components') { %>["styled-components", { "pure": true, "ssr": true }]<% } %>]
|
||||
"presets": ["@nrwl/next/babel"],
|
||||
"plugins": [
|
||||
<% if (style === 'styled-components') { %>["styled-components", { "pure": true, "ssr": true }]<% } %>
|
||||
]
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { NormalizedSchema } from './normalize-options';
|
||||
import { Tree } from '@nrwl/devkit';
|
||||
import { updateBabelJestConfig } from '@nrwl/react/src/rules/update-babel-jest-config';
|
||||
|
||||
export function updateJestConfig(host: Tree, options: NormalizedSchema) {
|
||||
if (options.unitTestRunner !== 'jest') {
|
||||
@ -14,11 +13,4 @@ export function updateJestConfig(host: Tree, options: NormalizedSchema) {
|
||||
"transform: {\n '^(?!.*\\\\.(js|jsx|ts|tsx|css|json)$)': '@nrwl/react/plugins/jest',"
|
||||
);
|
||||
host.write(configPath, content);
|
||||
|
||||
updateBabelJestConfig(host, options.appProjectRoot, (json) => {
|
||||
if (options.style === 'styled-jsx') {
|
||||
json.plugins = (json.plugins || []).concat('styled-jsx/babel');
|
||||
}
|
||||
return json;
|
||||
});
|
||||
}
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
import * as path from 'path';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
import { readJson, Tree } from '@nrwl/devkit';
|
||||
import updateBabelConfig from './update-babel-config';
|
||||
|
||||
describe('Migrate babel setup', () => {
|
||||
let tree: Tree;
|
||||
|
||||
beforeEach(async () => {
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
});
|
||||
|
||||
it(`should add web babel preset if it does not exist`, async () => {
|
||||
tree.write(
|
||||
'workspace.json',
|
||||
JSON.stringify({
|
||||
projects: {
|
||||
app1: {
|
||||
root: 'apps/app1',
|
||||
},
|
||||
app2: {
|
||||
root: 'apps/app2',
|
||||
},
|
||||
app3: {
|
||||
root: 'apps/app3',
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
tree.write(
|
||||
'nx.json',
|
||||
JSON.stringify({
|
||||
projects: {
|
||||
app1: {},
|
||||
app2: {},
|
||||
app3: {},
|
||||
},
|
||||
})
|
||||
);
|
||||
tree.write(
|
||||
'apps/app1/.babelrc',
|
||||
JSON.stringify({
|
||||
presets: ['@nrwl/react/babel'],
|
||||
})
|
||||
);
|
||||
tree.write(
|
||||
'apps/app2/.babelrc',
|
||||
JSON.stringify({ presets: ['next/babel'] })
|
||||
);
|
||||
|
||||
await updateBabelConfig(tree);
|
||||
|
||||
expect(readJson(tree, 'apps/app1/.babelrc')).toMatchObject({
|
||||
presets: ['@nrwl/react/babel'],
|
||||
});
|
||||
|
||||
expect(readJson(tree, 'apps/app2/.babelrc')).toMatchObject({
|
||||
presets: ['@nrwl/next/babel'],
|
||||
});
|
||||
|
||||
expect(tree.exists('apps/app3/.babelrc')).not.toBeTruthy();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,22 @@
|
||||
import { formatFiles, getProjects, Tree, updateJson } from '@nrwl/devkit';
|
||||
|
||||
export async function updateBabelConfig(host: Tree) {
|
||||
const projects = getProjects(host);
|
||||
|
||||
projects.forEach((p) => {
|
||||
const babelrcPath = `${p.root}/.babelrc`;
|
||||
if (!host.exists(babelrcPath)) return;
|
||||
|
||||
updateJson(host, babelrcPath, (json) => {
|
||||
json.presets = json.presets || [];
|
||||
json.presets = json.presets.map((x) =>
|
||||
x === 'next/babel' ? '@nrwl/next/babel' : x
|
||||
);
|
||||
return json;
|
||||
});
|
||||
});
|
||||
|
||||
await formatFiles(host);
|
||||
}
|
||||
|
||||
export default updateBabelConfig;
|
||||
@ -337,33 +337,13 @@ describe('app', () => {
|
||||
displayName: 'my-node-app',
|
||||
preset: '../../jest.preset.js',
|
||||
transform: {
|
||||
'^.+\\\\\\\\.[tj]s$': [
|
||||
'babel-jest',
|
||||
{ cwd: __dirname, configFile: './babel-jest.config.json' },
|
||||
],
|
||||
'^.+\\\\\\\\.[tj]s$': 'babel-jest',
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'js', 'html'],
|
||||
coverageDirectory: '../../coverage/apps/my-node-app',
|
||||
};
|
||||
"
|
||||
`);
|
||||
|
||||
expect(readJsonInTree(tree, 'apps/my-node-app/babel-jest.config.json'))
|
||||
.toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"presets": Array [
|
||||
Array [
|
||||
"@babel/preset-env",
|
||||
Object {
|
||||
"targets": Object {
|
||||
"node": "current",
|
||||
},
|
||||
},
|
||||
],
|
||||
"@babel/preset-typescript",
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
describe('--js flag', () => {
|
||||
|
||||
@ -449,34 +449,13 @@ describe('lib', () => {
|
||||
displayName: 'my-lib',
|
||||
preset: '../../jest.preset.js',
|
||||
transform: {
|
||||
'^.+\\\\\\\\.[tj]sx?$': [
|
||||
'babel-jest',
|
||||
{ cwd: __dirname, configFile: './babel-jest.config.json' },
|
||||
],
|
||||
'^.+\\\\\\\\.[tj]sx?$': 'babel-jest',
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||
coverageDirectory: '../../coverage/libs/my-lib',
|
||||
};
|
||||
"
|
||||
`);
|
||||
|
||||
expect(readJsonInTree(tree, 'libs/my-lib/babel-jest.config.json'))
|
||||
.toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"presets": Array [
|
||||
Array [
|
||||
"@babel/preset-env",
|
||||
Object {
|
||||
"targets": Object {
|
||||
"node": "current",
|
||||
},
|
||||
},
|
||||
],
|
||||
"@babel/preset-typescript",
|
||||
"@babel/preset-react",
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
describe('--js flag', () => {
|
||||
|
||||
@ -5,6 +5,9 @@
|
||||
module.exports = function (api: any, options: {}) {
|
||||
api.assertVersion(7);
|
||||
return {
|
||||
presets: [[require.resolve('@babel/preset-react'), { useBuiltIns: true }]],
|
||||
presets: [
|
||||
'@nrwl/web/babel',
|
||||
[require.resolve('@babel/preset-react'), { useBuiltIns: true }],
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
@ -565,12 +565,7 @@ describe('app', () => {
|
||||
});
|
||||
|
||||
const babelrc = readJson(appTree, 'apps/my-app/.babelrc');
|
||||
const babelJestConfig = readJson(
|
||||
appTree,
|
||||
'apps/my-app/babel-jest.config.json'
|
||||
);
|
||||
expect(babelrc.plugins).toContain('styled-jsx/babel');
|
||||
expect(babelJestConfig.plugins).toContain('styled-jsx/babel');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { updateBabelJestConfig } from '../../../rules/update-babel-jest-config';
|
||||
import { updateJestConfigContent } from '../../../utils/jest-utils';
|
||||
import { NormalizedSchema } from '../schema';
|
||||
import { offsetFromRoot, Tree, updateJson } from '@nrwl/devkit';
|
||||
@ -26,11 +25,4 @@ export function updateJestConfig(host: Tree, options: NormalizedSchema) {
|
||||
const originalContent = host.read(configPath).toString();
|
||||
const content = updateJestConfigContent(originalContent);
|
||||
host.write(configPath, content);
|
||||
|
||||
updateBabelJestConfig(host, options.appProjectRoot, (json) => {
|
||||
if (options.style === 'styled-jsx') {
|
||||
json.plugins = (json.plugins || []).concat('styled-jsx/babel');
|
||||
}
|
||||
return json;
|
||||
});
|
||||
}
|
||||
|
||||
@ -487,10 +487,6 @@ describe('lib', () => {
|
||||
|
||||
const workspaceJson = readJson(appTree, '/workspace.json');
|
||||
const babelrc = readJson(appTree, 'libs/my-lib/.babelrc');
|
||||
const babelJestConfig = readJson(
|
||||
appTree,
|
||||
'libs/my-lib/babel-jest.config.json'
|
||||
);
|
||||
|
||||
expect(workspaceJson.projects['my-lib'].architect.build).toMatchObject({
|
||||
options: {
|
||||
@ -498,7 +494,6 @@ describe('lib', () => {
|
||||
},
|
||||
});
|
||||
expect(babelrc.plugins).toContain('styled-jsx/babel');
|
||||
expect(babelJestConfig.plugins).toContain('styled-jsx/babel');
|
||||
});
|
||||
|
||||
it('should support style none', async () => {
|
||||
|
||||
@ -19,7 +19,6 @@ import {
|
||||
typesReactRouterDomVersion,
|
||||
} from '../../utils/versions';
|
||||
import { Schema } from './schema';
|
||||
import { updateBabelJestConfig } from '../../rules/update-babel-jest-config';
|
||||
import {
|
||||
addDependenciesToPackageJson,
|
||||
addProjectConfiguration,
|
||||
@ -95,13 +94,6 @@ export async function libraryGenerator(host: Tree, schema: Schema) {
|
||||
babelJest: true,
|
||||
});
|
||||
tasks.push(jestTask);
|
||||
|
||||
updateBabelJestConfig(host, options.projectRoot, (json) => {
|
||||
if (options.style === 'styled-jsx') {
|
||||
json.plugins = (json.plugins || []).concat('styled-jsx/babel');
|
||||
}
|
||||
return json;
|
||||
});
|
||||
}
|
||||
|
||||
if (options.component) {
|
||||
|
||||
@ -1,31 +0,0 @@
|
||||
import { readJson, Tree } from '@nrwl/devkit';
|
||||
import { updateBabelJestConfig } from './update-babel-jest-config';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
|
||||
describe('updateBabelJestConfig', () => {
|
||||
let tree: Tree;
|
||||
|
||||
beforeEach(() => {
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
});
|
||||
|
||||
it('should update babel-jest.config.json', async () => {
|
||||
tree.write('/apps/demo/babel-jest.config.json', JSON.stringify({}));
|
||||
|
||||
updateBabelJestConfig(tree, '/apps/demo', (json) => {
|
||||
json.plugins = ['test'];
|
||||
return json;
|
||||
});
|
||||
|
||||
const config = readJson(tree, '/apps/demo/babel-jest.config.json');
|
||||
expect(config.plugins).toEqual(['test']);
|
||||
});
|
||||
|
||||
it('should do nothing if project does not use babel jest', async () => {
|
||||
updateBabelJestConfig(tree, '/apps/demo', (json) => {
|
||||
json.plugins = ['test'];
|
||||
return json;
|
||||
});
|
||||
expect(tree.exists('/apps/demo/babel-jest.config.json')).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -1,14 +0,0 @@
|
||||
import { Tree, updateJson } from '@nrwl/devkit';
|
||||
|
||||
type BabelJestConfigUpdater<T> = (json: T) => T;
|
||||
|
||||
export function updateBabelJestConfig<T = any>(
|
||||
host: Tree,
|
||||
projectRoot: string,
|
||||
update: BabelJestConfigUpdater<T>
|
||||
) {
|
||||
const configPath = `${projectRoot}/babel-jest.config.json`;
|
||||
if (host.exists(configPath)) {
|
||||
updateJson(host, configPath, update);
|
||||
}
|
||||
}
|
||||
@ -25,18 +25,23 @@ module.exports = function (api: any, options: NxReactBabelPresetOptions = {}) {
|
||||
// Support module/nomodule pattern.
|
||||
[
|
||||
require.resolve('@babel/preset-env'),
|
||||
{
|
||||
// Allow importing core-js in entrypoint and use browserlist to select polyfills.
|
||||
// This is needed for differential loading as well.
|
||||
useBuiltIns: 'entry',
|
||||
corejs: 3,
|
||||
// Do not transform modules to CJS
|
||||
modules: false,
|
||||
targets: isModern ? { esmodules: true } : undefined,
|
||||
bugfixes: true,
|
||||
// Exclude transforms that make all code slower
|
||||
exclude: ['transform-typeof-symbol'],
|
||||
},
|
||||
// For Jest tests, NODE_ENV is set as 'test' and we only want to set target as Node.
|
||||
// All other options will fail in Jest since Node does not support some ES features
|
||||
// such as import syntax.
|
||||
process.env.NODE_ENV === 'test'
|
||||
? { targets: { node: 'current' } }
|
||||
: {
|
||||
// Allow importing core-js in entrypoint and use browserlist to select polyfills.
|
||||
// This is needed for differential loading as well.
|
||||
useBuiltIns: 'entry',
|
||||
corejs: 3,
|
||||
// Do not transform modules to CJS
|
||||
modules: false,
|
||||
targets: isModern ? { esmodules: true } : undefined,
|
||||
bugfixes: true,
|
||||
// Exclude transforms that make all code slower
|
||||
exclude: ['transform-typeof-symbol'],
|
||||
},
|
||||
],
|
||||
require.resolve('@babel/preset-typescript'),
|
||||
],
|
||||
|
||||
@ -14,6 +14,12 @@
|
||||
"version": "9.2.0-beta.1",
|
||||
"description": "Set buildLibsFromSource property to true to not break existing projects.",
|
||||
"factory": "./src/migrations/update-9-2-0/set-build-libs-from-source"
|
||||
},
|
||||
"update-babel-config-11.5.0": {
|
||||
"cli": "nx",
|
||||
"version": "11.5.0-beta.1",
|
||||
"description": "Update babel config to support different TS setup",
|
||||
"factory": "./src/migrations/update-11-5-0/update-babel-config"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,31 +354,13 @@ describe('app', () => {
|
||||
preset: '../../jest.preset.js',
|
||||
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
|
||||
transform: {
|
||||
'^.+\\\\\\\\.[tj]s$': [ 'babel-jest',
|
||||
{ cwd: __dirname, configFile: './babel-jest.config.json' }]
|
||||
'^.+\\\\\\\\.[tj]s$': 'babel-jest'
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'js', 'html'],
|
||||
coverageDirectory: '../../coverage/apps/my-app'
|
||||
};
|
||||
"
|
||||
`);
|
||||
|
||||
expect(readJson(tree, 'apps/my-app/babel-jest.config.json'))
|
||||
.toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"presets": Array [
|
||||
Array [
|
||||
"@babel/preset-env",
|
||||
Object {
|
||||
"targets": Object {
|
||||
"node": "current",
|
||||
},
|
||||
},
|
||||
],
|
||||
"@babel/preset-typescript",
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1 +1,5 @@
|
||||
{}
|
||||
{
|
||||
"presets": [
|
||||
"@nrwl/web/babel"
|
||||
]
|
||||
}
|
||||
|
||||
@ -42,7 +42,6 @@ function initRootBabelConfig(tree: Tree) {
|
||||
}
|
||||
|
||||
writeJson(tree, '/babel.config.json', {
|
||||
presets: ['@nrwl/web/babel'],
|
||||
babelrcRoots: ['*'], // Make sure .babelrc files other than root can be loaded in a monorepo
|
||||
});
|
||||
}
|
||||
|
||||
@ -0,0 +1,104 @@
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
import { readJson, Tree } from '@nrwl/devkit';
|
||||
import { updateBabelConfig } from './update-babel-config';
|
||||
describe('Migrate babel setup', () => {
|
||||
let tree: Tree;
|
||||
|
||||
beforeEach(async () => {
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
});
|
||||
|
||||
it(`should add web babel preset if it does not exist`, async () => {
|
||||
tree.write(
|
||||
'workspace.json',
|
||||
JSON.stringify({
|
||||
projects: {
|
||||
app1: {
|
||||
root: 'apps/app1',
|
||||
projectType: 'application',
|
||||
},
|
||||
app2: {
|
||||
root: 'apps/app2',
|
||||
projectType: 'application',
|
||||
},
|
||||
app3: {
|
||||
root: 'apps/app3',
|
||||
projectType: 'application',
|
||||
},
|
||||
app4: {
|
||||
root: 'apps/app4',
|
||||
projectType: 'application',
|
||||
},
|
||||
app5: {
|
||||
root: 'apps/app5',
|
||||
projectType: 'application',
|
||||
},
|
||||
lib1: {
|
||||
root: 'libs/lib1',
|
||||
projectType: 'library',
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
tree.write(
|
||||
'nx.json',
|
||||
JSON.stringify({
|
||||
projects: {
|
||||
app1: {},
|
||||
app2: {},
|
||||
app3: {},
|
||||
app4: {},
|
||||
app5: {},
|
||||
lib1: {},
|
||||
},
|
||||
})
|
||||
);
|
||||
tree.write(
|
||||
'babel.config.json',
|
||||
JSON.stringify({
|
||||
presets: ['@nrwl/web/babel'],
|
||||
})
|
||||
);
|
||||
tree.write('apps/app1/.babelrc', JSON.stringify({}));
|
||||
tree.write(
|
||||
'apps/app2/.babelrc',
|
||||
JSON.stringify({ presets: ['@nrwl/web/babel'] })
|
||||
);
|
||||
tree.write(
|
||||
'apps/app3/.babelrc',
|
||||
JSON.stringify({ presets: ['@nrwl/react/babel'] })
|
||||
);
|
||||
tree.write(
|
||||
'apps/app4/.babelrc',
|
||||
JSON.stringify({ presets: ['@nrwl/gatsby/babel'] })
|
||||
);
|
||||
|
||||
await updateBabelConfig(tree);
|
||||
|
||||
expect(readJson(tree, 'babel.config.json').presets).not.toContain(
|
||||
'@nrwl/web/babel'
|
||||
);
|
||||
|
||||
expect(readJson(tree, 'apps/app1/.babelrc')).toMatchObject({
|
||||
presets: ['@nrwl/web/babel'],
|
||||
});
|
||||
|
||||
expect(readJson(tree, 'apps/app2/.babelrc')).toMatchObject({
|
||||
presets: ['@nrwl/web/babel'],
|
||||
});
|
||||
|
||||
expect(readJson(tree, 'apps/app3/.babelrc')).toMatchObject({
|
||||
presets: ['@nrwl/react/babel'],
|
||||
});
|
||||
|
||||
expect(readJson(tree, 'apps/app4/.babelrc')).toMatchObject({
|
||||
presets: ['@nrwl/gatsby/babel'],
|
||||
});
|
||||
|
||||
expect(tree.exists('apps/app5/.babelrc')).not.toBeTruthy();
|
||||
|
||||
expect(readJson(tree, 'libs/lib1/.babelrc')).toMatchObject({
|
||||
presets: ['@nrwl/web/babel'],
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,49 @@
|
||||
import { formatFiles, getProjects, Tree, updateJson } from '@nrwl/devkit';
|
||||
|
||||
export async function updateBabelConfig(host: Tree) {
|
||||
const projects = getProjects(host);
|
||||
|
||||
if (host.exists('babel.config.json')) {
|
||||
updateJson(host, 'babel.config.json', (json) => {
|
||||
if (Array.isArray(json.presets)) {
|
||||
json.presets = json.presets.filter((x) => x !== '@nrwl/web/babel');
|
||||
}
|
||||
return json;
|
||||
});
|
||||
}
|
||||
|
||||
projects.forEach((p) => {
|
||||
const babelrcPath = `${p.root}/.babelrc`;
|
||||
|
||||
// Add `@nrwl/web/babel` to projects that did not previously use it.
|
||||
// This is needed because we removed it from the root.
|
||||
if (host.exists(babelrcPath)) {
|
||||
updateJson(host, babelrcPath, (json) => {
|
||||
json.presets = json.presets || [];
|
||||
if (
|
||||
-1 ===
|
||||
json.presets.findIndex(
|
||||
(x) =>
|
||||
x === '@nrwl/web/babel' ||
|
||||
x === '@nrwl/react/babel' ||
|
||||
x === '@nrwl/gatsby/babel'
|
||||
)
|
||||
) {
|
||||
json.presets.push('@nrwl/web/babel');
|
||||
}
|
||||
return json;
|
||||
});
|
||||
// Non-buildable libraries might be included in applications that
|
||||
// require .babelrc to exist and contain '@nrwl/web/babel' preset
|
||||
} else if (p.projectType === 'library') {
|
||||
host.write(
|
||||
babelrcPath,
|
||||
JSON.stringify({ presets: ['@nrwl/web/babel'] }, null, 2)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
await formatFiles(host);
|
||||
}
|
||||
|
||||
export default updateBabelConfig;
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"presets": ["@nrwl/web/babel"]
|
||||
}
|
||||
@ -718,34 +718,16 @@ describe('lib', () => {
|
||||
displayName: 'my-lib',
|
||||
preset: '../../jest.preset.js',
|
||||
transform: {
|
||||
'^.+\\\\\\\\.[tj]sx?$': [ 'babel-jest',
|
||||
{ cwd: __dirname, configFile: './babel-jest.config.json' }]
|
||||
'^.+\\\\\\\\.[tj]sx?$': 'babel-jest'
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||
coverageDirectory: '../../coverage/libs/my-lib'
|
||||
};
|
||||
"
|
||||
`);
|
||||
|
||||
expect(readJson(tree, 'libs/my-lib/babel-jest.config.json'))
|
||||
.toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"presets": Array [
|
||||
Array [
|
||||
"@babel/preset-env",
|
||||
Object {
|
||||
"targets": Object {
|
||||
"node": "current",
|
||||
},
|
||||
},
|
||||
],
|
||||
"@babel/preset-typescript",
|
||||
"@babel/preset-react",
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('--pascalCaseFiles', () => {
|
||||
it('should generate files with upper case names', async () => {
|
||||
await libraryGenerator(tree, {
|
||||
@ -772,4 +754,23 @@ describe('lib', () => {
|
||||
).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('--skipBabelrc', () => {
|
||||
it('should skip generating .babelrc when --skipBabelrc=true', async () => {
|
||||
await libraryGenerator(tree, {
|
||||
...defaultOptions,
|
||||
name: 'myLib',
|
||||
skipBabelrc: true,
|
||||
});
|
||||
expect(tree.exists('libs/my-lib/.babelrc')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should generate .babelrc by default', async () => {
|
||||
await libraryGenerator(tree, {
|
||||
...defaultOptions,
|
||||
name: 'myLib',
|
||||
});
|
||||
expect(tree.exists('libs/my-lib/.babelrc')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -100,6 +100,7 @@ function createFiles(tree: Tree, options: NormalizedSchema) {
|
||||
|
||||
generateFiles(tree, join(__dirname, './files/lib'), options.projectRoot, {
|
||||
...options,
|
||||
dot: '.',
|
||||
className,
|
||||
name,
|
||||
propertyName,
|
||||
@ -117,6 +118,10 @@ function createFiles(tree: Tree, options: NormalizedSchema) {
|
||||
);
|
||||
}
|
||||
|
||||
if (options.skipBabelrc) {
|
||||
tree.delete(join(options.projectRoot, '.babelrc'));
|
||||
}
|
||||
|
||||
if (options.js) {
|
||||
toJS(tree);
|
||||
}
|
||||
|
||||
@ -15,4 +15,5 @@ export interface Schema {
|
||||
babelJest?: boolean;
|
||||
pascalCaseFiles?: boolean;
|
||||
strict?: boolean;
|
||||
skipBabelrc?: boolean;
|
||||
}
|
||||
|
||||
@ -81,6 +81,11 @@
|
||||
"type": "boolean",
|
||||
"description": "Whether to enable tsconfig strict mode or not.",
|
||||
"default": false
|
||||
},
|
||||
"skipBabelrc": {
|
||||
"type": "boolean",
|
||||
"description": "Do not generate .babelrc file. Useful for Node libraries that are not compiled by Babel",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
"required": ["name"]
|
||||
|
||||
@ -49,7 +49,6 @@ describe('preset', () => {
|
||||
expect(tree.children('apps/proj')).toMatchSnapshot();
|
||||
expect(tree.children('apps/proj/src/')).toMatchSnapshot();
|
||||
expect(tree.children('apps/proj/src/app')).toMatchSnapshot();
|
||||
console.log(tree.children(''));
|
||||
|
||||
expect(
|
||||
JSON.parse(tree.read('/workspace.json').toString()).cli.defaultCollection
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user