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:
Jack Hsu 2021-03-09 16:32:36 -05:00 committed by GitHub
parent 372b7939c6
commit ddec362a5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 378 additions and 265 deletions

View File

@ -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`

View File

@ -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`

View File

@ -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`

View File

@ -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 }],
],
};
};

View File

@ -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();

View File

@ -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'

View File

@ -1,14 +0,0 @@
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "current"
}
}
],
"@babel/preset-typescript"<% if (supportTsx) { %>,
"@babel/preset-react"<% } %>
]
}

View File

@ -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'],<% } %><% } %>

View File

@ -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",
],
}
`);
});
});
});

View File

@ -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'));
}
}

View File

@ -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
View 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 }]],
};
};

View File

@ -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": {

View File

@ -32,6 +32,7 @@
"next": "^10.0.1"
},
"dependencies": {
"@babel/plugin-proposal-decorators": "^7.8.3",
"@nrwl/react": "*",
"@nrwl/cypress": "*",
"@nrwl/jest": "*",

View File

@ -28,12 +28,19 @@ function withNx(nextConfig = {} as any) {
const userWebpack = nextConfig.webpack || ((x) => x);
return {
...nextConfig,
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`.
*/
webpack: (config, options) => {
// Include workspace libs in css/sass loaders
const includes = [join(appRootPath, workspaceLayout().libsDir)];

View File

@ -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();

View File

@ -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 }]<% } %>
]
}

View File

@ -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;
});
}

View File

@ -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();
});
});

View File

@ -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;

View File

@ -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', () => {

View File

@ -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', () => {

View File

@ -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 }],
],
};
};

View File

@ -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');
});
});

View File

@ -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;
});
}

View File

@ -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 () => {

View File

@ -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) {

View File

@ -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);
});
});

View File

@ -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);
}
}

View File

@ -25,7 +25,12 @@ module.exports = function (api: any, options: NxReactBabelPresetOptions = {}) {
// Support module/nomodule pattern.
[
require.resolve('@babel/preset-env'),
{
// 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',

View File

@ -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"
}
}
}

View File

@ -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",
],
}
`);
});
});
});

View File

@ -1 +1,5 @@
{}
{
"presets": [
"@nrwl/web/babel"
]
}

View File

@ -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
});
}

View File

@ -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'],
});
});
});

View File

@ -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;

View File

@ -0,0 +1,3 @@
{
"presets": ["@nrwl/web/babel"]
}

View File

@ -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();
});
});
});

View File

@ -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);
}

View File

@ -15,4 +15,5 @@ export interface Schema {
babelJest?: boolean;
pascalCaseFiles?: boolean;
strict?: boolean;
skipBabelrc?: boolean;
}

View File

@ -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"]

View File

@ -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