feat(react): refactored babel support so options are more easily customized (#3089)
This reverts commit 7679df22f5b90d085b5f32f2135d828036ee5aa7.
This commit is contained in:
parent
a6220f7b0a
commit
d593153a33
@ -16,7 +16,7 @@ List of static assets.
|
||||
|
||||
Type: `string`
|
||||
|
||||
Path to a function which takes a babel config and returns an updated babel config
|
||||
(deprecated) Path to a function which takes a babel config and returns an updated babel config
|
||||
|
||||
### entryFile
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ List of static assets.
|
||||
|
||||
Type: `string`
|
||||
|
||||
Path to a function which takes a babel config and returns an updated babel config
|
||||
(deprecated) Path to a function which takes a babel config and returns an updated babel config
|
||||
|
||||
### entryFile
|
||||
|
||||
|
||||
@ -199,7 +199,7 @@ forEachCli((currentCLIName) => {
|
||||
);
|
||||
}, 120000);
|
||||
|
||||
xit('should be able to use babel-jest', async () => {
|
||||
it('should be able to use babel-jest', async () => {
|
||||
ensureProject();
|
||||
const appName = uniq('app');
|
||||
const libName = uniq('lib');
|
||||
@ -211,11 +211,6 @@ forEachCli((currentCLIName) => {
|
||||
`generate @nrwl/react:lib ${libName} --no-interactive --babelJest`
|
||||
);
|
||||
|
||||
checkFilesExist(
|
||||
`apps/${appName}/babel-jest.config.json`,
|
||||
`libs/${libName}/babel-jest.config.json`
|
||||
);
|
||||
|
||||
const appTestResults = await runCLIAsync(`test ${appName}`);
|
||||
expect(appTestResults.stderr).toContain('Test Suites: 1 passed, 1 total');
|
||||
|
||||
@ -308,7 +303,7 @@ forEachCli((currentCLIName) => {
|
||||
}
|
||||
checkFilesExist(...filesToCheck);
|
||||
expect(readFile(`dist/apps/${appName}/main.js`)).toContain(
|
||||
'var App = () => {'
|
||||
'const App = () =>'
|
||||
);
|
||||
runCLI(`build ${appName} --prod --output-hashing none`);
|
||||
filesToCheck = [
|
||||
|
||||
@ -175,7 +175,7 @@ export function newProject(): void {
|
||||
`@nrwl/storybook`,
|
||||
`@nrwl/nx-plugin`,
|
||||
];
|
||||
yarnAdd(packages.join(` `));
|
||||
yarnAdd([`@nrwl/eslint-plugin-nx`].concat(packages).join(` `));
|
||||
packages
|
||||
.filter((f) => f != '@nrwl/nx-plugin')
|
||||
.forEach((p) => {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { stripIndents } from '@angular-devkit/core/src/utils/literals';
|
||||
import {
|
||||
checkFilesExist,
|
||||
ensureProject,
|
||||
@ -6,7 +5,6 @@ import {
|
||||
readFile,
|
||||
runCLI,
|
||||
runCLIAsync,
|
||||
supportUi,
|
||||
uniq,
|
||||
updateFile,
|
||||
} from './utils';
|
||||
@ -54,72 +52,9 @@ forEachCli((currentCLIName) => {
|
||||
const lintE2eResults = runCLI(`lint ${appName}-e2e`);
|
||||
expect(lintE2eResults).toContain('All files pass linting.');
|
||||
|
||||
if (supportUi()) {
|
||||
const e2eResults = runCLI(`e2e ${appName}-e2e`);
|
||||
expect(e2eResults).toContain('All specs passed!');
|
||||
}
|
||||
const e2eResults = runCLI(`e2e ${appName}-e2e`);
|
||||
expect(e2eResults).toContain('All specs passed!');
|
||||
}, 120000);
|
||||
|
||||
it('should support same syntax as TypeScript', () => {
|
||||
ensureProject();
|
||||
const appName = uniq('app');
|
||||
|
||||
runCLI(`generate @nrwl/web:app ${appName} --no-interactive`);
|
||||
|
||||
const mainPath = `apps/${appName}/src/app/app.element.ts`;
|
||||
const content = readFile(mainPath);
|
||||
updateFile(
|
||||
mainPath,
|
||||
content
|
||||
// Testing decorators
|
||||
.replace(
|
||||
`export class AppElement extends HTMLElement`,
|
||||
stripIndents`
|
||||
function myDecorator(ctor) {
|
||||
ctor.title = '${appName}';
|
||||
}
|
||||
|
||||
@myDecorator
|
||||
export class AppElement extends HTMLElement`
|
||||
)
|
||||
.replace('${title}', '${(AppElement as any).title}') +
|
||||
// Testing const enums
|
||||
stripIndents`
|
||||
export const enum MyEnum {
|
||||
a,
|
||||
b,
|
||||
b
|
||||
};
|
||||
`
|
||||
);
|
||||
|
||||
if (supportUi()) {
|
||||
const e2eResults = runCLI(`e2e ${appName}-e2e`);
|
||||
expect(e2eResults).toContain('All specs passed!');
|
||||
}
|
||||
});
|
||||
|
||||
it('should support CSS modules', () => {
|
||||
ensureProject();
|
||||
const appName = uniq('app');
|
||||
|
||||
runCLI(`generate @nrwl/web:app ${appName} --no-interactive`);
|
||||
updateFile(
|
||||
`apps/${appName}/src/app/app.module.css`,
|
||||
'.foo { color: red; }'
|
||||
);
|
||||
const mainPath = `apps/${appName}/src/app/app.element.ts`;
|
||||
const content = readFile(mainPath);
|
||||
updateFile(
|
||||
mainPath,
|
||||
`import styles from './app.module.css';\n${content}`
|
||||
);
|
||||
|
||||
if (supportUi()) {
|
||||
const e2eResults = runCLI(`e2e ${appName}-e2e`);
|
||||
expect(e2eResults).toContain('All specs passed!');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('CLI - Environment Variables', () => {
|
||||
@ -140,7 +75,7 @@ forEachCli((currentCLIName) => {
|
||||
env: { ...process.env, NODE_ENV: 'test', NX_BUILD: '52', NX_API: 'QA' },
|
||||
});
|
||||
expect(readFile(`dist/apps/${appName}/main.js`)).toContain(
|
||||
'var envVars = ["test", "52", "QA"];'
|
||||
'const envVars = ["test", "52", "QA"];'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
22
package.json
22
package.json
@ -50,13 +50,13 @@
|
||||
"@angular/router": "^9.1.0",
|
||||
"@angular/service-worker": "^9.1.0",
|
||||
"@angular/upgrade": "^9.1.0",
|
||||
"@babel/core": "7.8.4",
|
||||
"@babel/core": "7.9.6",
|
||||
"@babel/preset-env": "7.9.6",
|
||||
"@babel/plugin-proposal-class-properties": "7.8.3",
|
||||
"@babel/plugin-proposal-decorators": "7.8.3",
|
||||
"@babel/plugin-transform-regenerator": "7.8.3",
|
||||
"@babel/preset-env": "7.8.4",
|
||||
"@babel/preset-react": "7.8.3",
|
||||
"@babel/preset-typescript": "7.8.3",
|
||||
"@babel/plugin-transform-regenerator": "7.8.7",
|
||||
"@babel/preset-typescript": "7.9.0",
|
||||
"@babel/preset-react": "7.9.4",
|
||||
"@bazel/bazel": "^1.2.0",
|
||||
"@bazel/ibazel": "^0.10.3",
|
||||
"@cypress/webpack-preprocessor": "^4.1.2",
|
||||
@ -73,6 +73,7 @@
|
||||
"@ngrx/store-devtools": "9.1.0",
|
||||
"@ngtools/webpack": "~9.1.0",
|
||||
"@reduxjs/toolkit": "1.3.2",
|
||||
"@rollup/plugin-babel": "5.0.2",
|
||||
"@rollup/plugin-commonjs": "11.0.2",
|
||||
"@rollup/plugin-image": "2.0.4",
|
||||
"@rollup/plugin-node-resolve": "7.1.1",
|
||||
@ -110,12 +111,12 @@
|
||||
"app-root-path": "^2.0.1",
|
||||
"autoprefixer": "9.7.4",
|
||||
"axios": "^0.19.0",
|
||||
"babel-loader": "8.0.6",
|
||||
"babel-plugin-const-enum": "^0.0.5",
|
||||
"babel-loader": "8.1.0",
|
||||
"babel-plugin-const-enum": "^1.0.1",
|
||||
"babel-plugin-macros": "^2.8.0",
|
||||
"babel-plugin-transform-async-to-promises": "^0.8.15",
|
||||
"babel-plugin-emotion": "^10.0.29",
|
||||
"babel-plugin-macros": "2.6.1",
|
||||
"babel-plugin-styled-components": "^1.10.7",
|
||||
"babel-plugin-transform-async-to-promises": "0.8.15",
|
||||
"browserslist": "4.8.7",
|
||||
"cacache": "12.0.2",
|
||||
"caniuse-lite": "^1.0.30001030",
|
||||
@ -126,7 +127,7 @@
|
||||
"confusing-browser-globals": "^1.0.9",
|
||||
"conventional-changelog-cli": "^2.0.23",
|
||||
"copy-webpack-plugin": "5.1.1",
|
||||
"core-js": "^2.6.9",
|
||||
"core-js": "^3.6.5",
|
||||
"cosmiconfig": "^4.0.0",
|
||||
"css-loader": "3.4.2",
|
||||
"cypress": "^4.1.0",
|
||||
@ -197,7 +198,6 @@
|
||||
"regenerator-runtime": "0.13.3",
|
||||
"release-it": "^7.4.0",
|
||||
"rollup": "1.31.1",
|
||||
"rollup-plugin-babel": "4.3.3",
|
||||
"rollup-plugin-copy": "3.3.0",
|
||||
"rollup-plugin-filesize": "6.2.1",
|
||||
"rollup-plugin-local-resolve": "1.0.7",
|
||||
|
||||
@ -23,7 +23,6 @@ describe('init', () => {
|
||||
expect(dependencies['@angular/platform-browser']).toBeDefined();
|
||||
expect(dependencies['@angular/platform-browser-dynamic']).toBeDefined();
|
||||
expect(dependencies['@angular/router']).toBeDefined();
|
||||
expect(dependencies['core-js']).toBeDefined();
|
||||
expect(dependencies['rxjs']).toBeDefined();
|
||||
expect(dependencies['zone.js']).toBeDefined();
|
||||
expect(devDependencies['@angular/compiler-cli']).toBeDefined();
|
||||
|
||||
@ -34,7 +34,6 @@ const updateDependencies = addDepsToPackageJson(
|
||||
'@angular/platform-browser': angularVersion,
|
||||
'@angular/platform-browser-dynamic': angularVersion,
|
||||
'@angular/router': angularVersion,
|
||||
'core-js': '^2.5.4',
|
||||
rxjs: rxjsVersion,
|
||||
'zone.js': '^0.10.2',
|
||||
},
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||
<% if (isLibrary) { %>
|
||||
import 'core-js/es7/reflect';
|
||||
import 'zone.js/dist/zone';
|
||||
<% } %>
|
||||
import 'zone.js/dist/zone-testing';
|
||||
|
||||
@ -135,7 +135,6 @@ module.exports = function(config) {
|
||||
appTree
|
||||
);
|
||||
const testTs = resultTree.read('libs/lib1/src/test.ts').toString();
|
||||
expect(testTs).toContain("import 'core-js/es7/reflect';");
|
||||
expect(testTs).toContain("import 'zone.js/dist/zone';");
|
||||
});
|
||||
});
|
||||
@ -199,7 +198,6 @@ module.exports = function(config) {
|
||||
appTree
|
||||
);
|
||||
const testTs = resultTree.read('apps/app1/src/test.ts').toString();
|
||||
expect(testTs).not.toContain("import 'core-js/es7/reflect';");
|
||||
expect(testTs).not.toContain("import 'zone.js/dist/zone';");
|
||||
});
|
||||
});
|
||||
|
||||
@ -133,38 +133,6 @@ describe('jestProject', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('--babelJest', () => {
|
||||
it('should have a babel config when true', async () => {
|
||||
const resultTree = await runSchematic(
|
||||
'jest-project',
|
||||
{
|
||||
project: 'lib1',
|
||||
setupFile: 'none',
|
||||
babelJest: true,
|
||||
},
|
||||
appTree
|
||||
);
|
||||
expect(
|
||||
resultTree.exists('/libs/lib1/babel-jest.config.json')
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should NOT have a babel config when false', async () => {
|
||||
const resultTree = await runSchematic(
|
||||
'jest-project',
|
||||
{
|
||||
project: 'lib1',
|
||||
setupFile: 'none',
|
||||
babelJest: false,
|
||||
},
|
||||
appTree
|
||||
);
|
||||
expect(
|
||||
resultTree.exists('/libs/lib1/babel-jest.config.json')
|
||||
).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('--setup-file', () => {
|
||||
it('should generate src/test-setup.ts', async () => {
|
||||
const resultTree = await runSchematic(
|
||||
|
||||
@ -3,8 +3,8 @@ export const jestVersion = '25.2.3';
|
||||
export const jestTypesVersion = '25.1.4';
|
||||
export const tsJestVersion = '25.2.1';
|
||||
|
||||
export const babelCoreVersion = '7.8.4';
|
||||
export const babelPresetEnvVersion = '7.8.4';
|
||||
export const babelPresetTypescriptVersion = '7.8.3';
|
||||
export const babelPresetReactVersion = '7.8.3';
|
||||
export const babelCoreVersion = '7.9.6';
|
||||
export const babelPresetEnvVersion = '7.9.6';
|
||||
export const babelPresetTypescriptVersion = '7.9.0';
|
||||
export const babelPresetReactVersion = '7.9.4';
|
||||
export const babelJestVersion = '25.1.0';
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{
|
||||
"presets": ["next/babel"],
|
||||
"plugins": [<% if (style === 'styled-components') { %>["styled-components", { "pure": true, "ssr": true }]<% } %> ]
|
||||
"plugins": [<% if (style === 'styled-components') { %>["styled-components", { "pure": true, "ssr": true }]<% } %>]
|
||||
}
|
||||
|
||||
10
packages/react/babel.ts
Normal file
10
packages/react/babel.ts
Normal file
@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Babel preset to provide React support for Nx.
|
||||
*/
|
||||
|
||||
module.exports = function (api: any, options: {}) {
|
||||
api.assertVersion(7);
|
||||
return {
|
||||
presets: [[require.resolve('@babel/preset-react'), { useBuiltIns: true }]],
|
||||
};
|
||||
};
|
||||
@ -39,6 +39,16 @@
|
||||
"version": "8.12.0-beta.1",
|
||||
"description": "Ensure React correct webpack config and babel preset",
|
||||
"factory": "./src/migrations/update-8-12-0/fix-react-files-8-12-0"
|
||||
},
|
||||
"update-9.4.0": {
|
||||
"version": "9.4.0-beta.1",
|
||||
"description": "Update libraries",
|
||||
"factory": "./src/migrations/update-9-4-0/update-9-4-0"
|
||||
},
|
||||
"babelrc-9.4.0": {
|
||||
"version": "9.4.0-beta.1",
|
||||
"description": "Migrate to new babel setup for greater flexibility",
|
||||
"factory": "./src/migrations/update-9-4-0/babelrc-9-4-0"
|
||||
}
|
||||
},
|
||||
"packageJsonUpdates": {
|
||||
@ -181,6 +191,79 @@
|
||||
"alwaysAddToPackageJson": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"9.4.0": {
|
||||
"version": "9.4.0-beta.1",
|
||||
"packages": {
|
||||
"react": {
|
||||
"version": "16.13.1",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"react-dom": {
|
||||
"version": "16.13.1",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@types/react": {
|
||||
"version": "16.9.35",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"version": "16.9.8",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@types/react-is": {
|
||||
"version": "16.7.1",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"styled-components": {
|
||||
"version": "5.1.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@types/styled-components": {
|
||||
"version": "5.1.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"react-router-dom": {
|
||||
"version": "5.2.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@types/react-router-dom": {
|
||||
"version": "5.1.5",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@testing-library/react": {
|
||||
"version": "10.0.4",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@reduxjs/toolkit": {
|
||||
"version": "1.3.6",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"react-redux": {
|
||||
"version": "7.2.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@types/react-redux": {
|
||||
"version": "7.1.9",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"eslint-plugin-import": {
|
||||
"version": "2.20.2",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"eslint-plugin-react": {
|
||||
"version": "7.20.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"eslint-plugin-react-hooks": {
|
||||
"version": "4.0.2",
|
||||
"alwaysAddToPackageJson": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,15 +31,13 @@
|
||||
"@nrwl/workspace": "*"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.8.4",
|
||||
"@babel/preset-react": "^7.8.3",
|
||||
"@babel/core": "7.9.6",
|
||||
"@babel/preset-react": "7.9.4",
|
||||
"@nrwl/cypress": "*",
|
||||
"@nrwl/jest": "*",
|
||||
"@nrwl/web": "*",
|
||||
"@angular-devkit/schematics": "~9.1.0",
|
||||
"@svgr/webpack": "^5.2.0",
|
||||
"babel-plugin-emotion": "^10.0.29",
|
||||
"babel-plugin-styled-components": "^1.10.7",
|
||||
"confusing-browser-globals": "^1.0.9",
|
||||
"eslint-plugin-import": "^2.20.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.2.3",
|
||||
|
||||
@ -1,12 +1,7 @@
|
||||
import { Configuration } from 'webpack';
|
||||
import { updateBabelOptions } from '../src/utils/babel-utils';
|
||||
|
||||
// Add React-specific configuration
|
||||
function getWebpackConfig(config: Configuration) {
|
||||
const idx = config.module.rules.findIndex((r) => r.loader === 'babel-loader');
|
||||
const babelRuleOptions = config.module.rules[idx].options as any;
|
||||
updateBabelOptions(babelRuleOptions);
|
||||
|
||||
config.module.rules.push(
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|webp)$/,
|
||||
|
||||
@ -0,0 +1,74 @@
|
||||
import { Tree } from '@angular-devkit/schematics';
|
||||
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
|
||||
import * as path from 'path';
|
||||
import { createEmptyWorkspace } from '@nrwl/workspace/testing';
|
||||
import { createApp, createLib, createWebApp } from '../../utils/testing';
|
||||
|
||||
describe('Migrate babel setup', () => {
|
||||
let tree: Tree;
|
||||
let schematicRunner: SchematicTestRunner;
|
||||
|
||||
beforeEach(async () => {
|
||||
tree = Tree.empty();
|
||||
tree = createEmptyWorkspace(tree);
|
||||
schematicRunner = new SchematicTestRunner(
|
||||
'@nrwl/react',
|
||||
path.join(__dirname, '../../../migrations.json')
|
||||
);
|
||||
tree.overwrite(
|
||||
'package.json',
|
||||
JSON.stringify({
|
||||
dependencies: {
|
||||
react: '16.13.1',
|
||||
'react-dom': '16.13.1',
|
||||
},
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it(`should create .babelrc for projects without them`, async () => {
|
||||
tree = await createApp(tree, 'demo');
|
||||
tree = await createLib(tree, 'ui');
|
||||
|
||||
tree = await schematicRunner
|
||||
.runSchematicAsync('babelrc-9.4.0', {}, tree)
|
||||
.toPromise();
|
||||
|
||||
expect(tree.exists('/babel.config.json')).toBe(true);
|
||||
expect(tree.exists('/apps/demo/.babelrc')).toBe(true);
|
||||
expect(tree.exists('/libs/ui/.babelrc')).toBe(true);
|
||||
});
|
||||
|
||||
it(`should not overwrite existing .babelrc files`, async () => {
|
||||
tree = await createApp(tree, 'demo');
|
||||
tree.create('/apps/demo/.babelrc', '{}');
|
||||
|
||||
tree = await schematicRunner
|
||||
.runSchematicAsync('babelrc-9.4.0', {}, tree)
|
||||
.toPromise();
|
||||
|
||||
const content = tree.read('/apps/demo/.babelrc').toString();
|
||||
expect(content).toEqual('{}');
|
||||
});
|
||||
|
||||
it(`should not migrate non-React projects`, async () => {
|
||||
tree = await createWebApp(tree, 'demo');
|
||||
|
||||
tree = await schematicRunner
|
||||
.runSchematicAsync('babelrc-9.4.0', {}, tree)
|
||||
.toPromise();
|
||||
|
||||
expect(tree.exists('/apps/demo/.babelrc')).toBe(false);
|
||||
});
|
||||
|
||||
it(`should not overwrite babel.config.js file`, async () => {
|
||||
tree.create('/babel.config.js', 'module.exports = {};');
|
||||
|
||||
tree = await schematicRunner
|
||||
.runSchematicAsync('babelrc-9.4.0', {}, tree)
|
||||
.toPromise();
|
||||
|
||||
expect(tree.exists('/babel.config.js')).toBe(true);
|
||||
expect(tree.exists('/babel.config.json')).toBe(false);
|
||||
});
|
||||
});
|
||||
110
packages/react/src/migrations/update-9-4-0/babelrc-9-4-0.ts
Normal file
110
packages/react/src/migrations/update-9-4-0/babelrc-9-4-0.ts
Normal file
@ -0,0 +1,110 @@
|
||||
import {
|
||||
chain,
|
||||
Rule,
|
||||
SchematicContext,
|
||||
Tree,
|
||||
} from '@angular-devkit/schematics';
|
||||
import { getFullProjectGraphFromHost } from '@nrwl/workspace/src/utils/ast-utils';
|
||||
import {
|
||||
stripIndent,
|
||||
stripIndents,
|
||||
} from '@angular-devkit/core/src/utils/literals';
|
||||
import { initRootBabelConfig } from '@nrwl/web/src/utils/rules';
|
||||
|
||||
/*
|
||||
* This migration will do a few things:
|
||||
*
|
||||
* - Create the base babel.config.json file if it doesn't already exist
|
||||
* - Create .babelrc files for each React project that doesn't already have one
|
||||
* - For any projects that are not migrated, display a message so users are not surprised.
|
||||
*/
|
||||
export default function update(): Rule {
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
const updates = [];
|
||||
const conflicts: Array<[string, string]> = [];
|
||||
const projectGraph = getFullProjectGraphFromHost(host);
|
||||
if (host.exists('/babel.config.json')) {
|
||||
context.logger.info(
|
||||
`
|
||||
Found an existing babel.config.json file so we skipped creating it.
|
||||
|
||||
You may want to update it to include the Nx preset "@nrwl/web/babel".
|
||||
`
|
||||
);
|
||||
} else if (host.exists('/babel.config.js')) {
|
||||
context.logger.info(
|
||||
`
|
||||
Found an existing babel.config.js file so we skipped creating it.
|
||||
|
||||
You may want to update it to include the Nx preset "@nrwl/web/babel".
|
||||
`
|
||||
);
|
||||
} else {
|
||||
updates.push(initRootBabelConfig());
|
||||
}
|
||||
|
||||
Object.keys(projectGraph.nodes).forEach((name) => {
|
||||
const p = projectGraph.nodes[name];
|
||||
const deps = projectGraph.dependencies[name];
|
||||
const isReact = deps.some(
|
||||
(d) =>
|
||||
projectGraph.nodes[d.target].type === 'npm' &&
|
||||
d.target.indexOf('react') !== -1
|
||||
);
|
||||
if (isReact) {
|
||||
updates.push((host) => {
|
||||
const babelrcPath = `${p.data.root}/.babelrc`;
|
||||
if (host.exists(babelrcPath)) {
|
||||
conflicts.push([name, babelrcPath]);
|
||||
} else {
|
||||
createBabelrc(host, context, babelrcPath, deps);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (conflicts.length > 0) {
|
||||
context.logger.info(stripIndent`
|
||||
The following projects already have .babelrc so we did not create them:
|
||||
|
||||
${conflicts
|
||||
.map(([name, babelrc]) => `${name} - ${babelrc}`)
|
||||
.join('\n ')}
|
||||
|
||||
You may want to update them to include the Nx preset "@nrwl/react/babel".
|
||||
`);
|
||||
}
|
||||
|
||||
return chain(updates);
|
||||
};
|
||||
}
|
||||
|
||||
function createBabelrc(host, context, babelrcPath, deps) {
|
||||
const babelrc = {
|
||||
presets: ['@nrwl/react/babel'],
|
||||
plugins: [],
|
||||
};
|
||||
let added = 0;
|
||||
|
||||
if (deps.some((d) => d.target === 'npm:styled-components')) {
|
||||
babelrc.plugins.push(['styled-components', { pure: true, ssr: true }]);
|
||||
added++;
|
||||
}
|
||||
|
||||
if (deps.some((d) => d.target.startsWith('npm:@emotion'))) {
|
||||
babelrc.presets.push('@emotion/babel-preset-css-prop');
|
||||
added++;
|
||||
}
|
||||
|
||||
if (added > 1) {
|
||||
context.logger.warn(
|
||||
stripIndents`We created a babel config at ${babelrcPath} with both styled-components and emotion plugins.
|
||||
Only one should be used, please remove the unused plugin.
|
||||
|
||||
For example, if you don't use styled-components, then remove that plugin from the .babelrc file.
|
||||
`
|
||||
);
|
||||
}
|
||||
|
||||
host.create(babelrcPath, JSON.stringify(babelrc, null, 2));
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
import { Tree } from '@angular-devkit/schematics';
|
||||
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
|
||||
import { readJsonInTree } from '@nrwl/workspace';
|
||||
import * as path from 'path';
|
||||
import { createEmptyWorkspace } from '@nrwl/workspace/testing';
|
||||
|
||||
describe('Update 9.4.0', () => {
|
||||
let tree: Tree;
|
||||
let schematicRunner: SchematicTestRunner;
|
||||
|
||||
beforeEach(async () => {
|
||||
tree = Tree.empty();
|
||||
tree = createEmptyWorkspace(tree);
|
||||
schematicRunner = new SchematicTestRunner(
|
||||
'@nrwl/react',
|
||||
path.join(__dirname, '../../../migrations.json')
|
||||
);
|
||||
});
|
||||
|
||||
it(`should update libs`, async () => {
|
||||
tree.overwrite(
|
||||
'package.json',
|
||||
JSON.stringify({
|
||||
dependencies: {
|
||||
react: '16.12.1',
|
||||
},
|
||||
devDependencies: {
|
||||
'@types/react': '16.9.1',
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
tree = await schematicRunner
|
||||
.runSchematicAsync('update-9.4.0', {}, tree)
|
||||
.toPromise();
|
||||
|
||||
const packageJson = readJsonInTree(tree, '/package.json');
|
||||
expect(packageJson).toMatchObject({
|
||||
dependencies: {
|
||||
react: '16.13.1',
|
||||
},
|
||||
devDependencies: {
|
||||
'@types/react': '16.9.35',
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
13
packages/react/src/migrations/update-9-4-0/update-9-4-0.ts
Normal file
13
packages/react/src/migrations/update-9-4-0/update-9-4-0.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { chain, Rule } from '@angular-devkit/schematics';
|
||||
import { formatFiles, updatePackagesInPackageJson } from '@nrwl/workspace';
|
||||
import * as path from 'path';
|
||||
|
||||
export default function update(): Rule {
|
||||
return chain([
|
||||
updatePackagesInPackageJson(
|
||||
path.join(__dirname, '../../../', 'migrations.json'),
|
||||
'9.4.0'
|
||||
),
|
||||
formatFiles(),
|
||||
]);
|
||||
}
|
||||
13
packages/react/src/rules/add-styled-dependencies.ts
Normal file
13
packages/react/src/rules/add-styled-dependencies.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { noop, Rule } from '@angular-devkit/schematics';
|
||||
import { addDepsToPackageJson } from '@nrwl/workspace';
|
||||
import { CSS_IN_JS_DEPENDENCIES } from '../utils/styled';
|
||||
|
||||
export function addStyledModuleDependencies(styledModule: string): Rule {
|
||||
const extraDependencies = CSS_IN_JS_DEPENDENCIES[styledModule];
|
||||
return extraDependencies
|
||||
? addDepsToPackageJson(
|
||||
extraDependencies.dependencies,
|
||||
extraDependencies.devDependencies
|
||||
)
|
||||
: noop();
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
import { Tree } from '@angular-devkit/schematics';
|
||||
import { createEmptyWorkspace } from '@nrwl/workspace/testing';
|
||||
import * as stripJsonComments from 'strip-json-comments';
|
||||
import { readJsonInTree, NxJson } from '@nrwl/workspace';
|
||||
import { NxJson, readJsonInTree } from '@nrwl/workspace';
|
||||
import { runSchematic } from '../../utils/testing';
|
||||
|
||||
describe('app', () => {
|
||||
@ -44,6 +44,7 @@ describe('app', () => {
|
||||
|
||||
it('should generate files', async () => {
|
||||
const tree = await runSchematic('app', { name: 'myApp' }, appTree);
|
||||
expect(tree.exists('apps/my-app/.babelrc')).toBeTruthy();
|
||||
expect(tree.exists('apps/my-app/src/main.tsx')).toBeTruthy();
|
||||
expect(tree.exists('apps/my-app/src/app/app.tsx')).toBeTruthy();
|
||||
expect(tree.exists('apps/my-app/src/app/app.spec.tsx')).toBeTruthy();
|
||||
|
||||
@ -1,63 +1,27 @@
|
||||
import { join, JsonObject, normalize, Path } from '@angular-devkit/core';
|
||||
import {
|
||||
apply,
|
||||
chain,
|
||||
externalSchematic,
|
||||
filter,
|
||||
mergeWith,
|
||||
move,
|
||||
noop,
|
||||
Rule,
|
||||
SchematicContext,
|
||||
template,
|
||||
Tree,
|
||||
url,
|
||||
} from '@angular-devkit/schematics';
|
||||
import {
|
||||
addLintFiles,
|
||||
formatFiles,
|
||||
generateProjectLint,
|
||||
insert,
|
||||
names,
|
||||
NxJson,
|
||||
offsetFromRoot,
|
||||
toFileName,
|
||||
updateJsonInTree,
|
||||
updateWorkspace,
|
||||
} from '@nrwl/workspace';
|
||||
import {
|
||||
addDepsToPackageJson,
|
||||
appsDir,
|
||||
updateWorkspaceInTree,
|
||||
} from '@nrwl/workspace/src/utils/ast-utils';
|
||||
import { toJS } from '@nrwl/workspace/src/utils/rules/to-js';
|
||||
import * as ts from 'typescript';
|
||||
import { assertValidStyle } from '../../utils/assertion';
|
||||
import { addInitialRoutes } from '../../utils/ast-utils';
|
||||
import { updateJestConfigContent } from '../../utils/jest-utils';
|
||||
import { addLintFiles, formatFiles } from '@nrwl/workspace';
|
||||
import { extraEslintDependencies, reactEslintJson } from '../../utils/lint';
|
||||
import { CSS_IN_JS_DEPENDENCIES } from '../../utils/styled';
|
||||
import {
|
||||
reactRouterDomVersion,
|
||||
typesReactRouterDomVersion,
|
||||
} from '../../utils/versions';
|
||||
import init from '../init/init';
|
||||
import { Schema } from './schema';
|
||||
|
||||
interface NormalizedSchema extends Schema {
|
||||
projectName: string;
|
||||
appProjectRoot: Path;
|
||||
e2eProjectName: string;
|
||||
parsedTags: string[];
|
||||
fileName: string;
|
||||
styledModule: null | string;
|
||||
hasStyles: boolean;
|
||||
}
|
||||
import { createApplicationFiles } from './lib/create-application-files';
|
||||
import { updateJestConfig } from './lib/update-jest-config';
|
||||
import { normalizeOptions } from './lib/normalize-options';
|
||||
import { addProject } from './lib/add-project';
|
||||
import { addCypress } from './lib/add-cypress';
|
||||
import { addJest } from './lib/add-jest';
|
||||
import { addRouting } from './lib/add-routing';
|
||||
import { setDefaults } from './lib/set-defaults';
|
||||
import { updateNxJson } from './lib/update-nx-json';
|
||||
import { addStyledModuleDependencies } from '../../rules/add-styled-dependencies';
|
||||
|
||||
export default function (schema: Schema): Rule {
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
const options = normalizeOptions(host, schema);
|
||||
|
||||
return chain([
|
||||
init({
|
||||
...options,
|
||||
@ -73,283 +37,10 @@ export default function (schema: Schema): Rule {
|
||||
addCypress(options),
|
||||
addJest(options),
|
||||
updateJestConfig(options),
|
||||
addStyledModuleDependencies(options),
|
||||
addStyledModuleDependencies(options.styledModule),
|
||||
addRouting(options, context),
|
||||
setDefaults(options),
|
||||
formatFiles(options),
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
||||
function createApplicationFiles(options: NormalizedSchema): Rule {
|
||||
return mergeWith(
|
||||
apply(url(`./files/app`), [
|
||||
template({
|
||||
...names(options.name),
|
||||
...options,
|
||||
tmpl: '',
|
||||
offsetFromRoot: offsetFromRoot(options.appProjectRoot),
|
||||
}),
|
||||
options.styledModule || !options.hasStyles
|
||||
? filter((file) => !file.endsWith(`.${options.style}`))
|
||||
: noop(),
|
||||
options.unitTestRunner === 'none'
|
||||
? filter((file) => file !== `/src/app/${options.fileName}.spec.tsx`)
|
||||
: noop(),
|
||||
move(options.appProjectRoot),
|
||||
options.js ? toJS() : noop(),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
function updateJestConfig(options: NormalizedSchema): Rule {
|
||||
return options.unitTestRunner === 'none'
|
||||
? noop()
|
||||
: (host) => {
|
||||
const configPath = `${options.appProjectRoot}/jest.config.js`;
|
||||
const originalContent = host.read(configPath).toString();
|
||||
const content = updateJestConfigContent(originalContent);
|
||||
host.overwrite(configPath, content);
|
||||
};
|
||||
}
|
||||
|
||||
function updateNxJson(options: NormalizedSchema): Rule {
|
||||
return updateJsonInTree<NxJson>('nx.json', (json) => {
|
||||
json.projects[options.projectName] = { tags: options.parsedTags };
|
||||
return json;
|
||||
});
|
||||
}
|
||||
|
||||
function addProject(options: NormalizedSchema): Rule {
|
||||
return updateWorkspaceInTree((json) => {
|
||||
const architect: { [key: string]: any } = {};
|
||||
|
||||
architect.build = {
|
||||
builder: '@nrwl/web:build',
|
||||
options: {
|
||||
outputPath: join(normalize('dist'), options.appProjectRoot),
|
||||
index: join(options.appProjectRoot, 'src/index.html'),
|
||||
main: join(options.appProjectRoot, maybeJs(options, `src/main.tsx`)),
|
||||
polyfills: join(
|
||||
options.appProjectRoot,
|
||||
maybeJs(options, 'src/polyfills.ts')
|
||||
),
|
||||
tsConfig: join(options.appProjectRoot, 'tsconfig.app.json'),
|
||||
assets: [
|
||||
join(options.appProjectRoot, 'src/favicon.ico'),
|
||||
join(options.appProjectRoot, 'src/assets'),
|
||||
],
|
||||
styles:
|
||||
options.styledModule || !options.hasStyles
|
||||
? []
|
||||
: [join(options.appProjectRoot, `src/styles.${options.style}`)],
|
||||
scripts: [],
|
||||
webpackConfig: '@nrwl/react/plugins/webpack',
|
||||
},
|
||||
configurations: {
|
||||
production: {
|
||||
fileReplacements: [
|
||||
{
|
||||
replace: join(
|
||||
options.appProjectRoot,
|
||||
maybeJs(options, `src/environments/environment.ts`)
|
||||
),
|
||||
with: join(
|
||||
options.appProjectRoot,
|
||||
maybeJs(options, `src/environments/environment.prod.ts`)
|
||||
),
|
||||
},
|
||||
],
|
||||
optimization: true,
|
||||
outputHashing: 'all',
|
||||
sourceMap: false,
|
||||
extractCss: true,
|
||||
namedChunks: false,
|
||||
extractLicenses: true,
|
||||
vendorChunk: false,
|
||||
budgets: [
|
||||
{
|
||||
type: 'initial',
|
||||
maximumWarning: '2mb',
|
||||
maximumError: '5mb',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
architect.serve = {
|
||||
builder: '@nrwl/web:dev-server',
|
||||
options: {
|
||||
buildTarget: `${options.projectName}:build`,
|
||||
},
|
||||
configurations: {
|
||||
production: {
|
||||
buildTarget: `${options.projectName}:build:production`,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
architect.lint = generateProjectLint(
|
||||
normalize(options.appProjectRoot),
|
||||
join(normalize(options.appProjectRoot), 'tsconfig.app.json'),
|
||||
options.linter
|
||||
);
|
||||
|
||||
json.projects[options.projectName] = {
|
||||
root: options.appProjectRoot,
|
||||
sourceRoot: join(options.appProjectRoot, 'src'),
|
||||
projectType: 'application',
|
||||
schematics: {},
|
||||
architect,
|
||||
};
|
||||
|
||||
json.defaultProject = json.defaultProject || options.projectName;
|
||||
|
||||
return json;
|
||||
});
|
||||
}
|
||||
|
||||
function addCypress(options: NormalizedSchema): Rule {
|
||||
return options.e2eTestRunner === 'cypress'
|
||||
? externalSchematic('@nrwl/cypress', 'cypress-project', {
|
||||
...options,
|
||||
name: options.name + '-e2e',
|
||||
directory: options.directory,
|
||||
project: options.projectName,
|
||||
})
|
||||
: noop();
|
||||
}
|
||||
|
||||
function addJest(options: NormalizedSchema): Rule {
|
||||
return options.unitTestRunner === 'jest'
|
||||
? externalSchematic('@nrwl/jest', 'jest-project', {
|
||||
project: options.projectName,
|
||||
supportTsx: true,
|
||||
skipSerializers: true,
|
||||
setupFile: 'none',
|
||||
babelJest: options.babelJest,
|
||||
})
|
||||
: noop();
|
||||
}
|
||||
|
||||
function addStyledModuleDependencies(options: NormalizedSchema): Rule {
|
||||
const extraDependencies = CSS_IN_JS_DEPENDENCIES[options.styledModule];
|
||||
|
||||
return extraDependencies
|
||||
? addDepsToPackageJson(
|
||||
extraDependencies.dependencies,
|
||||
extraDependencies.devDependencies
|
||||
)
|
||||
: noop();
|
||||
}
|
||||
|
||||
function addRouting(
|
||||
options: NormalizedSchema,
|
||||
context: SchematicContext
|
||||
): Rule {
|
||||
return options.routing
|
||||
? chain([
|
||||
function addRouterToComponent(host: Tree) {
|
||||
const appPath = join(
|
||||
options.appProjectRoot,
|
||||
maybeJs(options, `src/app/${options.fileName}.tsx`)
|
||||
);
|
||||
const appFileContent = host.read(appPath).toString('utf-8');
|
||||
const appSource = ts.createSourceFile(
|
||||
appPath,
|
||||
appFileContent,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
|
||||
insert(host, appPath, addInitialRoutes(appPath, appSource, context));
|
||||
},
|
||||
addDepsToPackageJson(
|
||||
{ 'react-router-dom': reactRouterDomVersion },
|
||||
{ '@types/react-router-dom': typesReactRouterDomVersion }
|
||||
),
|
||||
])
|
||||
: noop();
|
||||
}
|
||||
|
||||
function setDefaults(options: NormalizedSchema): Rule {
|
||||
return options.skipWorkspaceJson
|
||||
? noop()
|
||||
: updateWorkspace((workspace) => {
|
||||
workspace.extensions.schematics = jsonIdentity(
|
||||
workspace.extensions.schematics || {}
|
||||
);
|
||||
workspace.extensions.schematics['@nrwl/react'] =
|
||||
workspace.extensions.schematics['@nrwl/react'] || {};
|
||||
const prev = jsonIdentity(
|
||||
workspace.extensions.schematics['@nrwl/react']
|
||||
);
|
||||
|
||||
workspace.extensions.schematics = {
|
||||
...workspace.extensions.schematics,
|
||||
'@nrwl/react': {
|
||||
...prev,
|
||||
application: {
|
||||
style: options.style,
|
||||
linter: options.linter,
|
||||
...jsonIdentity(prev.application),
|
||||
},
|
||||
component: {
|
||||
style: options.style,
|
||||
...jsonIdentity(prev.component),
|
||||
},
|
||||
library: {
|
||||
style: options.style,
|
||||
linter: options.linter,
|
||||
...jsonIdentity(prev.library),
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function jsonIdentity(x: any): JsonObject {
|
||||
return x as JsonObject;
|
||||
}
|
||||
|
||||
function normalizeOptions(host: Tree, options: Schema): NormalizedSchema {
|
||||
const appDirectory = options.directory
|
||||
? `${toFileName(options.directory)}/${toFileName(options.name)}`
|
||||
: toFileName(options.name);
|
||||
|
||||
const appProjectName = appDirectory.replace(new RegExp('/', 'g'), '-');
|
||||
const e2eProjectName = `${appProjectName}-e2e`;
|
||||
|
||||
const appProjectRoot = normalize(`${appsDir(host)}/${appDirectory}`);
|
||||
|
||||
const parsedTags = options.tags
|
||||
? options.tags.split(',').map((s) => s.trim())
|
||||
: [];
|
||||
|
||||
const fileName = options.pascalCaseFiles ? 'App' : 'app';
|
||||
|
||||
const styledModule = /^(css|scss|less|styl|none)$/.test(options.style)
|
||||
? null
|
||||
: options.style;
|
||||
|
||||
assertValidStyle(options.style);
|
||||
|
||||
return {
|
||||
...options,
|
||||
name: toFileName(options.name),
|
||||
projectName: appProjectName,
|
||||
appProjectRoot,
|
||||
e2eProjectName,
|
||||
parsedTags,
|
||||
fileName,
|
||||
styledModule,
|
||||
hasStyles: options.style !== 'none',
|
||||
};
|
||||
}
|
||||
|
||||
function maybeJs(options: NormalizedSchema, path: string): string {
|
||||
return options.js && (path.endsWith('.ts') || path.endsWith('.tsx'))
|
||||
? path.replace(/\.tsx?$/, '.js')
|
||||
: path;
|
||||
}
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"presets": [
|
||||
"@nrwl/react/babel",
|
||||
<% if (style === '@emotion/styled') { %>"@emotion/babel-preset-css-prop"<% } %>
|
||||
],
|
||||
"plugins": [
|
||||
<% if (style === 'styled-components') { %>["styled-components", { "pure": true, "ssr": true }]<% } %>
|
||||
]
|
||||
}
|
||||
13
packages/react/src/schematics/application/lib/add-cypress.ts
Normal file
13
packages/react/src/schematics/application/lib/add-cypress.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { externalSchematic, noop, Rule } from '@angular-devkit/schematics';
|
||||
import { NormalizedSchema } from '../schema';
|
||||
|
||||
export function addCypress(options: NormalizedSchema): Rule {
|
||||
return options.e2eTestRunner === 'cypress'
|
||||
? externalSchematic('@nrwl/cypress', 'cypress-project', {
|
||||
...options,
|
||||
name: options.name + '-e2e',
|
||||
directory: options.directory,
|
||||
project: options.projectName,
|
||||
})
|
||||
: noop();
|
||||
}
|
||||
14
packages/react/src/schematics/application/lib/add-jest.ts
Normal file
14
packages/react/src/schematics/application/lib/add-jest.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { externalSchematic, noop, Rule } from '@angular-devkit/schematics';
|
||||
import { NormalizedSchema } from '../schema';
|
||||
|
||||
export function addJest(options: NormalizedSchema): Rule {
|
||||
return options.unitTestRunner === 'jest'
|
||||
? externalSchematic('@nrwl/jest', 'jest-project', {
|
||||
project: options.projectName,
|
||||
supportTsx: true,
|
||||
skipSerializers: true,
|
||||
setupFile: 'none',
|
||||
babelJest: options.babelJest,
|
||||
})
|
||||
: noop();
|
||||
}
|
||||
100
packages/react/src/schematics/application/lib/add-project.ts
Normal file
100
packages/react/src/schematics/application/lib/add-project.ts
Normal file
@ -0,0 +1,100 @@
|
||||
import { Rule } from '@angular-devkit/schematics';
|
||||
import { generateProjectLint, updateWorkspaceInTree } from '@nrwl/workspace';
|
||||
import { join, normalize } from '@angular-devkit/core';
|
||||
import { NormalizedSchema } from '../schema';
|
||||
|
||||
export function addProject(options: NormalizedSchema): Rule {
|
||||
return updateWorkspaceInTree((json) => {
|
||||
const architect: { [key: string]: any } = {};
|
||||
|
||||
architect.build = {
|
||||
builder: '@nrwl/web:build',
|
||||
options: {
|
||||
outputPath: join(normalize('dist'), options.appProjectRoot),
|
||||
index: join(options.appProjectRoot, 'src/index.html'),
|
||||
main: join(options.appProjectRoot, maybeJs(options, `src/main.tsx`)),
|
||||
polyfills: join(
|
||||
options.appProjectRoot,
|
||||
maybeJs(options, 'src/polyfills.ts')
|
||||
),
|
||||
tsConfig: join(options.appProjectRoot, 'tsconfig.app.json'),
|
||||
assets: [
|
||||
join(options.appProjectRoot, 'src/favicon.ico'),
|
||||
join(options.appProjectRoot, 'src/assets'),
|
||||
],
|
||||
styles:
|
||||
options.styledModule || !options.hasStyles
|
||||
? []
|
||||
: [join(options.appProjectRoot, `src/styles.${options.style}`)],
|
||||
scripts: [],
|
||||
webpackConfig: '@nrwl/react/plugins/webpack',
|
||||
},
|
||||
configurations: {
|
||||
production: {
|
||||
fileReplacements: [
|
||||
{
|
||||
replace: join(
|
||||
options.appProjectRoot,
|
||||
maybeJs(options, `src/environments/environment.ts`)
|
||||
),
|
||||
with: join(
|
||||
options.appProjectRoot,
|
||||
maybeJs(options, `src/environments/environment.prod.ts`)
|
||||
),
|
||||
},
|
||||
],
|
||||
optimization: true,
|
||||
outputHashing: 'all',
|
||||
sourceMap: false,
|
||||
extractCss: true,
|
||||
namedChunks: false,
|
||||
extractLicenses: true,
|
||||
vendorChunk: false,
|
||||
budgets: [
|
||||
{
|
||||
type: 'initial',
|
||||
maximumWarning: '2mb',
|
||||
maximumError: '5mb',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
architect.serve = {
|
||||
builder: '@nrwl/web:dev-server',
|
||||
options: {
|
||||
buildTarget: `${options.projectName}:build`,
|
||||
},
|
||||
configurations: {
|
||||
production: {
|
||||
buildTarget: `${options.projectName}:build:production`,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
architect.lint = generateProjectLint(
|
||||
normalize(options.appProjectRoot),
|
||||
join(normalize(options.appProjectRoot), 'tsconfig.app.json'),
|
||||
options.linter
|
||||
);
|
||||
|
||||
json.projects[options.projectName] = {
|
||||
root: options.appProjectRoot,
|
||||
sourceRoot: join(options.appProjectRoot, 'src'),
|
||||
projectType: 'application',
|
||||
schematics: {},
|
||||
architect,
|
||||
};
|
||||
|
||||
json.defaultProject = json.defaultProject || options.projectName;
|
||||
|
||||
return json;
|
||||
});
|
||||
}
|
||||
|
||||
function maybeJs(options: NormalizedSchema, path: string): string {
|
||||
return options.js && (path.endsWith('.ts') || path.endsWith('.tsx'))
|
||||
? path.replace(/\.tsx?$/, '.js')
|
||||
: path;
|
||||
}
|
||||
51
packages/react/src/schematics/application/lib/add-routing.ts
Normal file
51
packages/react/src/schematics/application/lib/add-routing.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import * as ts from 'typescript';
|
||||
import {
|
||||
chain,
|
||||
noop,
|
||||
Rule,
|
||||
SchematicContext,
|
||||
Tree,
|
||||
} from '@angular-devkit/schematics';
|
||||
import { join } from '@angular-devkit/core';
|
||||
import { addDepsToPackageJson, insert } from '@nrwl/workspace';
|
||||
import { addInitialRoutes } from '../../../utils/ast-utils';
|
||||
import { NormalizedSchema } from '../schema';
|
||||
import {
|
||||
reactRouterDomVersion,
|
||||
typesReactRouterDomVersion,
|
||||
} from '@nrwl/react/src/utils/versions';
|
||||
|
||||
export function addRouting(
|
||||
options: NormalizedSchema,
|
||||
context: SchematicContext
|
||||
): Rule {
|
||||
return options.routing
|
||||
? chain([
|
||||
function addRouterToComponent(host: Tree) {
|
||||
const appPath = join(
|
||||
options.appProjectRoot,
|
||||
maybeJs(options, `src/app/${options.fileName}.tsx`)
|
||||
);
|
||||
const appFileContent = host.read(appPath).toString('utf-8');
|
||||
const appSource = ts.createSourceFile(
|
||||
appPath,
|
||||
appFileContent,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
|
||||
insert(host, appPath, addInitialRoutes(appPath, appSource, context));
|
||||
},
|
||||
addDepsToPackageJson(
|
||||
{ 'react-router-dom': reactRouterDomVersion },
|
||||
{ '@types/react-router-dom': typesReactRouterDomVersion }
|
||||
),
|
||||
])
|
||||
: noop();
|
||||
}
|
||||
|
||||
function maybeJs(options: NormalizedSchema, path: string): string {
|
||||
return options.js && (path.endsWith('.ts') || path.endsWith('.tsx'))
|
||||
? path.replace(/\.tsx?$/, '.js')
|
||||
: path;
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
import {
|
||||
apply,
|
||||
filter,
|
||||
mergeWith,
|
||||
move,
|
||||
noop,
|
||||
Rule,
|
||||
template,
|
||||
url,
|
||||
} from '@angular-devkit/schematics';
|
||||
import { names, offsetFromRoot } from '@nrwl/workspace';
|
||||
import { toJS } from '@nrwl/workspace/src/utils/rules/to-js';
|
||||
import { NormalizedSchema } from '../schema';
|
||||
|
||||
export function createApplicationFiles(options: NormalizedSchema): Rule {
|
||||
return mergeWith(
|
||||
apply(url(`./files/app`), [
|
||||
template({
|
||||
...names(options.name),
|
||||
...options,
|
||||
tmpl: '',
|
||||
offsetFromRoot: offsetFromRoot(options.appProjectRoot),
|
||||
}),
|
||||
options.styledModule || !options.hasStyles
|
||||
? filter((file) => !file.endsWith(`.${options.style}`))
|
||||
: noop(),
|
||||
options.unitTestRunner === 'none'
|
||||
? filter((file) => file !== `/src/app/${options.fileName}.spec.tsx`)
|
||||
: noop(),
|
||||
move(options.appProjectRoot),
|
||||
options.js ? toJS() : noop(),
|
||||
])
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
import { Tree } from '@angular-devkit/schematics';
|
||||
import { normalize } from '@angular-devkit/core';
|
||||
import { toFileName } from '@nrwl/workspace';
|
||||
import { appsDir } from '@nrwl/workspace/src/utils/ast-utils';
|
||||
import { NormalizedSchema, Schema } from '../schema';
|
||||
import { assertValidStyle } from '../../../utils/assertion';
|
||||
|
||||
export function normalizeOptions(
|
||||
host: Tree,
|
||||
options: Schema
|
||||
): NormalizedSchema {
|
||||
const appDirectory = options.directory
|
||||
? `${toFileName(options.directory)}/${toFileName(options.name)}`
|
||||
: toFileName(options.name);
|
||||
|
||||
const appProjectName = appDirectory.replace(new RegExp('/', 'g'), '-');
|
||||
const e2eProjectName = `${appProjectName}-e2e`;
|
||||
|
||||
const appProjectRoot = normalize(`${appsDir(host)}/${appDirectory}`);
|
||||
|
||||
const parsedTags = options.tags
|
||||
? options.tags.split(',').map((s) => s.trim())
|
||||
: [];
|
||||
|
||||
const fileName = options.pascalCaseFiles ? 'App' : 'app';
|
||||
|
||||
const styledModule = /^(css|scss|less|styl|none)$/.test(options.style)
|
||||
? null
|
||||
: options.style;
|
||||
|
||||
assertValidStyle(options.style);
|
||||
|
||||
return {
|
||||
...options,
|
||||
name: toFileName(options.name),
|
||||
projectName: appProjectName,
|
||||
appProjectRoot,
|
||||
e2eProjectName,
|
||||
parsedTags,
|
||||
fileName,
|
||||
styledModule,
|
||||
hasStyles: options.style !== 'none',
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
import { noop, Rule } from '@angular-devkit/schematics';
|
||||
import { updateWorkspace } from '@nrwl/workspace';
|
||||
import { NormalizedSchema } from '../schema';
|
||||
import { JsonObject } from '@angular-devkit/core';
|
||||
|
||||
export function setDefaults(options: NormalizedSchema): Rule {
|
||||
return options.skipWorkspaceJson
|
||||
? noop()
|
||||
: updateWorkspace((workspace) => {
|
||||
workspace.extensions.schematics = jsonIdentity(
|
||||
workspace.extensions.schematics || {}
|
||||
);
|
||||
workspace.extensions.schematics['@nrwl/react'] =
|
||||
workspace.extensions.schematics['@nrwl/react'] || {};
|
||||
const prev = jsonIdentity(
|
||||
workspace.extensions.schematics['@nrwl/react']
|
||||
);
|
||||
|
||||
workspace.extensions.schematics = {
|
||||
...workspace.extensions.schematics,
|
||||
'@nrwl/react': {
|
||||
...prev,
|
||||
application: {
|
||||
style: options.style,
|
||||
linter: options.linter,
|
||||
...jsonIdentity(prev.application),
|
||||
},
|
||||
component: {
|
||||
style: options.style,
|
||||
...jsonIdentity(prev.component),
|
||||
},
|
||||
library: {
|
||||
style: options.style,
|
||||
linter: options.linter,
|
||||
...jsonIdentity(prev.library),
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function jsonIdentity(x: any): JsonObject {
|
||||
return x as JsonObject;
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
import { noop, Rule } from '@angular-devkit/schematics';
|
||||
import { updateJestConfigContent } from '@nrwl/react/src/utils/jest-utils';
|
||||
import { NormalizedSchema } from '../schema';
|
||||
|
||||
export function updateJestConfig(options: NormalizedSchema): Rule {
|
||||
return options.unitTestRunner === 'none'
|
||||
? noop()
|
||||
: (host) => {
|
||||
const configPath = `${options.appProjectRoot}/jest.config.js`;
|
||||
const originalContent = host.read(configPath).toString();
|
||||
const content = updateJestConfigContent(originalContent);
|
||||
host.overwrite(configPath, content);
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
import { Rule } from '@angular-devkit/schematics';
|
||||
import { NxJson, updateJsonInTree } from '@nrwl/workspace';
|
||||
import { NormalizedSchema } from '../schema';
|
||||
|
||||
export function updateNxJson(options: NormalizedSchema): Rule {
|
||||
return updateJsonInTree<NxJson>('nx.json', (json) => {
|
||||
json.projects[options.projectName] = { tags: options.parsedTags };
|
||||
return json;
|
||||
});
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
import { Linter } from '@nrwl/workspace';
|
||||
import { SupportedStyles } from 'packages/react/typings/style';
|
||||
import { Path } from '@angular-devkit/core';
|
||||
|
||||
export interface Schema {
|
||||
name: string;
|
||||
@ -17,3 +18,13 @@ export interface Schema {
|
||||
skipWorkspaceJson?: boolean;
|
||||
js?: boolean;
|
||||
}
|
||||
|
||||
export interface NormalizedSchema extends Schema {
|
||||
projectName: string;
|
||||
appProjectRoot: Path;
|
||||
e2eProjectName: string;
|
||||
parsedTags: string[];
|
||||
fileName: string;
|
||||
styledModule: null | string;
|
||||
hasStyles: boolean;
|
||||
}
|
||||
|
||||
@ -21,13 +21,13 @@ import {
|
||||
getProjectConfig,
|
||||
insert,
|
||||
} from '@nrwl/workspace/src/utils/ast-utils';
|
||||
import { CSS_IN_JS_DEPENDENCIES } from '../../utils/styled';
|
||||
import {
|
||||
typesReactRouterDomVersion,
|
||||
reactRouterDomVersion,
|
||||
typesReactRouterDomVersion,
|
||||
} from '../../utils/versions';
|
||||
import { assertValidStyle } from '../../utils/assertion';
|
||||
import { toJS } from '@nrwl/workspace/src/utils/rules/to-js';
|
||||
import { addStyledModuleDependencies } from '../../rules/add-styled-dependencies';
|
||||
|
||||
interface NormalizedSchema extends Schema {
|
||||
projectSourceRoot: Path;
|
||||
@ -42,7 +42,7 @@ export default function (schema: Schema): Rule {
|
||||
const options = await normalizeOptions(host, schema, context);
|
||||
return chain([
|
||||
createComponentFiles(options),
|
||||
addStyledModuleDependencies(options),
|
||||
addStyledModuleDependencies(options.styledModule),
|
||||
addExportsToBarrel(options),
|
||||
options.routing
|
||||
? addDepsToPackageJson(
|
||||
@ -73,17 +73,6 @@ function createComponentFiles(options: NormalizedSchema): Rule {
|
||||
);
|
||||
}
|
||||
|
||||
function addStyledModuleDependencies(options: NormalizedSchema): Rule {
|
||||
const extraDependencies = CSS_IN_JS_DEPENDENCIES[options.styledModule];
|
||||
|
||||
return extraDependencies
|
||||
? addDepsToPackageJson(
|
||||
extraDependencies.dependencies,
|
||||
extraDependencies.devDependencies
|
||||
)
|
||||
: noop();
|
||||
}
|
||||
|
||||
function addExportsToBarrel(options: NormalizedSchema): Rule {
|
||||
return async (host: Tree) => {
|
||||
const workspace = await getWorkspace(host);
|
||||
@ -95,6 +84,7 @@ function addExportsToBarrel(options: NormalizedSchema): Rule {
|
||||
options.projectSourceRoot,
|
||||
options.js ? 'index.js' : 'index.ts'
|
||||
);
|
||||
console.log('index', indexFilePath);
|
||||
const buffer = host.read(indexFilePath);
|
||||
if (!!buffer) {
|
||||
const indexSource = buffer!.toString('utf-8');
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"presets": [
|
||||
"@nrwl/react/babel",
|
||||
<% if (style === '@emotion/styled') { %>"@emotion/babel-preset-css-prop"<% } %>
|
||||
],
|
||||
"plugins": [
|
||||
<% if (style === 'styled-components') { %>["styled-components", { "pure": true, "ssr": true }]<% } %>
|
||||
]
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
import { Tree } from '@angular-devkit/schematics';
|
||||
import { createEmptyWorkspace } from '@nrwl/workspace/testing';
|
||||
import { readJsonInTree, updateJsonInTree } from '@nrwl/workspace';
|
||||
import { NxJson } from '@nrwl/workspace';
|
||||
import { NxJson, readJsonInTree, updateJsonInTree } from '@nrwl/workspace';
|
||||
import { runSchematic } from '../../utils/testing';
|
||||
|
||||
describe('lib', () => {
|
||||
@ -398,7 +397,7 @@ describe('lib', () => {
|
||||
|
||||
expect(workspaceJson.projects['my-lib'].architect.build).toMatchObject({
|
||||
options: {
|
||||
external: ['react', 'react-dom', 'styled-components'],
|
||||
external: ['react', 'react-dom', 'react-is', 'styled-components'],
|
||||
},
|
||||
});
|
||||
});
|
||||
@ -443,7 +442,7 @@ describe('lib', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should add package.json', async () => {
|
||||
it('should add package.json and .babelrc', async () => {
|
||||
const tree = await runSchematic(
|
||||
'lib',
|
||||
{
|
||||
@ -454,8 +453,8 @@ describe('lib', () => {
|
||||
);
|
||||
|
||||
const packageJson = readJsonInTree(tree, '/libs/my-lib/package.json');
|
||||
|
||||
expect(packageJson.name).toEqual('@proj/my-lib');
|
||||
expect(tree.exists('/libs/my-lib/.babelrc'));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -47,6 +47,7 @@ import {
|
||||
} from '../../utils/versions';
|
||||
import { Schema } from './schema';
|
||||
import { libsDir } from '@nrwl/workspace/src/utils/ast-utils';
|
||||
import { initRootBabelConfig } from '@nrwl/web/src/utils/rules';
|
||||
|
||||
export interface NormalizedSchema extends Schema {
|
||||
name: string;
|
||||
@ -99,6 +100,7 @@ export default function (schema: Schema): Rule {
|
||||
: noop(),
|
||||
options.publishable ? updateLibPackageNpmScope(options) : noop(),
|
||||
updateAppRoutes(options, context),
|
||||
initRootBabelConfig(),
|
||||
formatFiles(options),
|
||||
])(host, context);
|
||||
};
|
||||
|
||||
@ -1,7 +1,11 @@
|
||||
import {
|
||||
babelPluginStyledComponentsVersion,
|
||||
emotionBabelPresetCssPropVersion,
|
||||
emotionCoreVersion,
|
||||
emotionStyledVersion,
|
||||
reactIsVersion,
|
||||
styledComponentsVersion,
|
||||
typesReactIsVersion,
|
||||
typesStyledComponentsVersion,
|
||||
} from './versions';
|
||||
import { PackageDependencies } from './dependencies';
|
||||
@ -11,10 +15,13 @@ export const CSS_IN_JS_DEPENDENCIES: {
|
||||
} = {
|
||||
'styled-components': {
|
||||
dependencies: {
|
||||
'react-is': reactIsVersion,
|
||||
'styled-components': styledComponentsVersion,
|
||||
},
|
||||
devDependencies: {
|
||||
'@types/styled-components': typesStyledComponentsVersion,
|
||||
'@types/react-is': typesReactIsVersion,
|
||||
'babel-plugin-styled-components': babelPluginStyledComponentsVersion,
|
||||
},
|
||||
},
|
||||
'@emotion/styled': {
|
||||
@ -22,6 +29,8 @@ export const CSS_IN_JS_DEPENDENCIES: {
|
||||
'@emotion/styled': emotionStyledVersion,
|
||||
'@emotion/core': emotionCoreVersion,
|
||||
},
|
||||
devDependencies: {},
|
||||
devDependencies: {
|
||||
'@emotion/babel-preset-css-prop': emotionBabelPresetCssPropVersion,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -3,6 +3,7 @@ import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
|
||||
import { Rule, Tree } from '@angular-devkit/schematics';
|
||||
import { names } from '@nrwl/workspace/src/utils/name-utils';
|
||||
import { updateWorkspace } from '@nrwl/workspace/src/utils/workspace';
|
||||
import { readJsonInTree } from '@nrwl/workspace';
|
||||
|
||||
const testRunner = new SchematicTestRunner(
|
||||
'@nrwl/react',
|
||||
@ -32,9 +33,48 @@ export function callRule(rule: Rule, tree: Tree) {
|
||||
return testRunner.callRule(rule, tree).toPromise();
|
||||
}
|
||||
|
||||
export function updateNxJson(tree, update: (json: any) => any) {
|
||||
const updated = update(readJsonInTree(tree, '/nx.json'));
|
||||
tree.overwrite('/nx.json', JSON.stringify(updated));
|
||||
}
|
||||
|
||||
export function createApp(tree: Tree, appName: string): Promise<Tree> {
|
||||
const { fileName } = names(appName);
|
||||
|
||||
tree.create(
|
||||
`/apps/${fileName}/src/main.tsx`,
|
||||
`import ReactDOM from 'react-dom';\n`
|
||||
);
|
||||
|
||||
updateNxJson(tree, (json) => {
|
||||
json.projects[appName] = { tags: [] };
|
||||
return json;
|
||||
});
|
||||
|
||||
return callRule(
|
||||
updateWorkspace((workspace) => {
|
||||
workspace.projects.add({
|
||||
name: fileName,
|
||||
root: `apps/${fileName}`,
|
||||
projectType: 'application',
|
||||
sourceRoot: `apps/${fileName}/src`,
|
||||
targets: {},
|
||||
});
|
||||
}),
|
||||
tree
|
||||
);
|
||||
}
|
||||
|
||||
export function createWebApp(tree: Tree, appName: string): Promise<Tree> {
|
||||
const { fileName } = names(appName);
|
||||
|
||||
tree.create(`/apps/${fileName}/src/index.ts`, `\n`);
|
||||
|
||||
updateNxJson(tree, (json) => {
|
||||
json.projects[appName] = { tags: [] };
|
||||
return json;
|
||||
});
|
||||
|
||||
return callRule(
|
||||
updateWorkspace((workspace) => {
|
||||
workspace.projects.add({
|
||||
@ -52,7 +92,12 @@ export function createApp(tree: Tree, appName: string): Promise<Tree> {
|
||||
export function createLib(tree: Tree, libName: string): Promise<Tree> {
|
||||
const { fileName } = names(libName);
|
||||
|
||||
tree.create(`/libs/${fileName}/src/index.ts`, `\n`);
|
||||
tree.create(`/libs/${fileName}/src/index.ts`, `import React from 'react';\n`);
|
||||
|
||||
updateNxJson(tree, (json) => {
|
||||
json.projects[libName] = { tags: [] };
|
||||
return json;
|
||||
});
|
||||
|
||||
return callRule(
|
||||
updateWorkspace((workspace) => {
|
||||
|
||||
@ -1,26 +1,32 @@
|
||||
export const nxVersion = '*';
|
||||
|
||||
export const reactVersion = '16.12.0';
|
||||
export const reactDomVersion = '16.12.0';
|
||||
export const typesReactVersion = '16.9.17';
|
||||
export const typesReactDomVersion = '16.9.4';
|
||||
export const reactVersion = '16.13.1';
|
||||
export const reactDomVersion = '16.13.1';
|
||||
export const typesReactVersion = '16.9.35';
|
||||
export const typesReactDomVersion = '16.9.8';
|
||||
|
||||
export const styledComponentsVersion = '5.0.1';
|
||||
export const typesStyledComponentsVersion = '5.0.1';
|
||||
export const styledComponentsVersion = '5.1.0';
|
||||
export const typesStyledComponentsVersion = '5.1.0';
|
||||
|
||||
export const reactIsVersion = '16.13.1';
|
||||
export const typesReactIsVersion = '16.7.1';
|
||||
|
||||
export const emotionStyledVersion = '10.0.27';
|
||||
export const emotionCoreVersion = '10.0.27';
|
||||
export const emotionBabelPresetCssPropVersion = '10.0.27';
|
||||
|
||||
export const reactRouterDomVersion = '5.1.2';
|
||||
export const typesReactRouterDomVersion = '5.1.3';
|
||||
export const reactRouterDomVersion = '5.2.0';
|
||||
export const typesReactRouterDomVersion = '5.1.5';
|
||||
|
||||
export const testingLibraryReactVersion = '9.4.0';
|
||||
export const testingLibraryReactVersion = '10.0.4';
|
||||
|
||||
export const reduxjsToolkitVersion = '1.3.2';
|
||||
export const reactReduxVersion = '7.1.3';
|
||||
export const typesReactReduxVersion = '7.1.5';
|
||||
export const reduxjsToolkitVersion = '1.3.6';
|
||||
export const reactReduxVersion = '7.2.0';
|
||||
export const typesReactReduxVersion = '7.1.9';
|
||||
|
||||
export const eslintPluginImportVersion = '2.19.1';
|
||||
export const eslintPluginImportVersion = '2.20.2';
|
||||
export const eslintPluginJsxA11yVersion = '6.2.3';
|
||||
export const eslintPluginReactVersion = '7.17.0';
|
||||
export const eslintPluginReactHooksVersion = '2.3.0';
|
||||
export const eslintPluginReactVersion = '7.20.0';
|
||||
export const eslintPluginReactHooksVersion = '4.0.2';
|
||||
|
||||
export const babelPluginStyledComponentsVersion = '1.10.7';
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@nrwl/cypress": "*",
|
||||
"core-js": "^3.2.1",
|
||||
"core-js": "^3.6.5",
|
||||
"tree-kill": "1.2.2",
|
||||
"ts-loader": "5.3.1",
|
||||
"tsconfig-paths-webpack-plugin": "3.2.0",
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
export const nxVersion = '*';
|
||||
export const storybookVersion = '5.3.9';
|
||||
export const babelCoreVersion = '7.8.3';
|
||||
export const babelLoaderVersion = '8.0.6';
|
||||
export const babelPresetTypescriptVersion = '7.8.3';
|
||||
export const babelCoreVersion = '7.9.6';
|
||||
export const babelLoaderVersion = '8.1.0';
|
||||
export const babelPresetTypescriptVersion = '7.9.0';
|
||||
|
||||
53
packages/web/babel.ts
Normal file
53
packages/web/babel.ts
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Babel preset to provide TypeScript support and module/nomodule for Nx.
|
||||
*/
|
||||
|
||||
module.exports = function (api: any, options: {}) {
|
||||
api.assertVersion(7);
|
||||
|
||||
return {
|
||||
presets: [
|
||||
// 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: api.env('legacy') ? undefined : { esmodules: true },
|
||||
bugfixes: true,
|
||||
// Exclude transforms that make all code slower
|
||||
exclude: ['transform-typeof-symbol'],
|
||||
},
|
||||
],
|
||||
require.resolve('@babel/preset-typescript'),
|
||||
],
|
||||
plugins: [
|
||||
require.resolve('babel-plugin-macros'),
|
||||
// Must use legacy decorators to remain compatible with TypeScript.
|
||||
[require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }],
|
||||
[
|
||||
require.resolve('@babel/plugin-proposal-class-properties'),
|
||||
{ loose: true },
|
||||
],
|
||||
],
|
||||
overrides: [
|
||||
// Convert `const enum` to `enum`. The former cannot be supported by babel
|
||||
// but at least we can get it to not error out.
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
plugins: [
|
||||
[
|
||||
require.resolve('babel-plugin-const-enum'),
|
||||
{
|
||||
transform: 'removeConst',
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
@ -39,28 +39,29 @@
|
||||
"@angular-devkit/build-webpack": "~0.901.0",
|
||||
"@angular-devkit/core": "~9.1.0",
|
||||
"@angular-devkit/schematics": "~9.1.0",
|
||||
"@babel/core": "^7.8.4",
|
||||
"@babel/preset-env": "^7.8.4",
|
||||
"@babel/preset-typescript": "^7.8.3",
|
||||
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
||||
"@babel/plugin-proposal-decorators": "^7.8.3",
|
||||
"@babel/plugin-transform-regenerator": "^7.8.3",
|
||||
"@babel/core": "7.9.6",
|
||||
"@babel/preset-env": "7.9.6",
|
||||
"@babel/plugin-proposal-class-properties": "7.8.3",
|
||||
"@babel/plugin-proposal-decorators": "7.8.3",
|
||||
"@babel/plugin-transform-regenerator": "7.8.7",
|
||||
"@babel/preset-typescript": "7.9.0",
|
||||
"@rollup/plugin-commonjs": "11.0.2",
|
||||
"@rollup/plugin-babel": "5.0.2",
|
||||
"@rollup/plugin-image": "2.0.4",
|
||||
"@rollup/plugin-node-resolve": "7.1.1",
|
||||
"ajv": "6.10.2",
|
||||
"autoprefixer": "9.7.4",
|
||||
"babel-loader": "8.0.6",
|
||||
"babel-plugin-const-enum": "0.0.5",
|
||||
"babel-plugin-macros": "2.6.1",
|
||||
"babel-plugin-transform-async-to-promises": "0.8.15",
|
||||
"babel-loader": "8.1.0",
|
||||
"babel-plugin-const-enum": "^1.0.1",
|
||||
"babel-plugin-macros": "^2.8.0",
|
||||
"babel-plugin-transform-async-to-promises": "^0.8.15",
|
||||
"browserslist": "4.8.7",
|
||||
"cacache": "12.0.2",
|
||||
"caniuse-lite": "^1.0.30001030",
|
||||
"circular-dependency-plugin": "5.2.0",
|
||||
"clean-css": "4.2.1",
|
||||
"copy-webpack-plugin": "5.1.1",
|
||||
"core-js": "^3.2.1",
|
||||
"core-js": "^3.6.5",
|
||||
"css-loader": "3.4.2",
|
||||
"file-loader": "4.2.0",
|
||||
"find-cache-dir": "3.0.0",
|
||||
@ -84,13 +85,12 @@
|
||||
"rxjs": "^6.5.4",
|
||||
"regenerator-runtime": "0.13.3",
|
||||
"rollup": "1.31.1",
|
||||
"rollup-plugin-babel": "4.3.3",
|
||||
"rollup-plugin-copy": "3.3.0",
|
||||
"rollup-plugin-filesize": "6.2.1",
|
||||
"rollup-plugin-local-resolve": "1.0.7",
|
||||
"rollup-plugin-peer-deps-external": "2.2.2",
|
||||
"rollup-plugin-postcss": "2.1.1",
|
||||
"rollup-plugin-typescript2": "0.26.0",
|
||||
"rollup-plugin-copy": "^3.3.0",
|
||||
"rollup-plugin-filesize": "^9.0.0",
|
||||
"rollup-plugin-local-resolve": "^1.0.7",
|
||||
"rollup-plugin-peer-deps-external": "^2.2.2",
|
||||
"rollup-plugin-postcss": "^3.1.1",
|
||||
"rollup-plugin-typescript2": "^0.27.1",
|
||||
"sass": "1.22.9",
|
||||
"sass-loader": "8.0.2",
|
||||
"semver": "6.3.0",
|
||||
|
||||
@ -7,28 +7,22 @@ import {
|
||||
import { JsonObject } from '@angular-devkit/core';
|
||||
import { from, Observable, of } from 'rxjs';
|
||||
import { catchError, last, switchMap, tap } from 'rxjs/operators';
|
||||
import { runRollup } from './run-rollup';
|
||||
import { createBabelConfig as _createBabelConfig } from '../../utils/babel-config';
|
||||
import { getBabelInputPlugin } from '@rollup/plugin-babel';
|
||||
import * as autoprefixer from 'autoprefixer';
|
||||
import * as rollup from 'rollup';
|
||||
import * as babel from 'rollup-plugin-babel';
|
||||
import * as peerDepsExternal from 'rollup-plugin-peer-deps-external';
|
||||
import * as postcss from 'rollup-plugin-postcss';
|
||||
import * as filesize from 'rollup-plugin-filesize';
|
||||
import * as localResolve from 'rollup-plugin-local-resolve';
|
||||
import { PackageBuilderOptions } from '../../utils/types';
|
||||
import {
|
||||
normalizePackageOptions,
|
||||
NormalizedBundleBuilderOptions,
|
||||
NormalizedCopyAssetOption,
|
||||
} from '../../utils/normalize';
|
||||
import { toClassName } from '@nrwl/workspace/src/utils/name-utils';
|
||||
import { NodeJsSyncHost } from '@angular-devkit/core/node';
|
||||
import { BuildResult } from '@angular-devkit/build-webpack';
|
||||
import {
|
||||
readJsonFile,
|
||||
writeJsonFile,
|
||||
} from '@nrwl/workspace/src/utils/fileutils';
|
||||
import { createProjectGraph } from '@nrwl/workspace/src/core/project-graph';
|
||||
|
||||
import {
|
||||
calculateProjectDependencies,
|
||||
checkDependentProjectsHaveBeenBuilt,
|
||||
@ -36,8 +30,15 @@ import {
|
||||
DependentBuildableProjectNode,
|
||||
updateBuildableProjectPackageJsonDependencies,
|
||||
} from '@nrwl/workspace/src/utils/buildable-libs-utils';
|
||||
import { PackageBuilderOptions } from '../../utils/types';
|
||||
import { runRollup } from './run-rollup';
|
||||
import {
|
||||
NormalizedBundleBuilderOptions,
|
||||
NormalizedCopyAssetOption,
|
||||
normalizePackageOptions,
|
||||
} from '../../utils/normalize';
|
||||
import { getSourceRoot } from '../../utils/source-root';
|
||||
import { NodeJsSyncHost } from '@angular-devkit/core/node';
|
||||
import { createBabelConfig } from '../../utils/babel-config';
|
||||
|
||||
// These use require because the ES import isn't correct.
|
||||
const resolve = require('@rollup/plugin-node-resolve');
|
||||
@ -88,7 +89,8 @@ export function run(
|
||||
options,
|
||||
dependencies,
|
||||
context,
|
||||
packageJson
|
||||
packageJson,
|
||||
sourceRoot
|
||||
);
|
||||
|
||||
if (options.watch) {
|
||||
@ -155,7 +157,8 @@ function createRollupOptions(
|
||||
options: NormalizedBundleBuilderOptions,
|
||||
dependencies: DependentBuildableProjectNode[],
|
||||
context: BuilderContext,
|
||||
packageJson: any
|
||||
packageJson: any,
|
||||
sourceRoot: string
|
||||
): rollup.InputOptions {
|
||||
const compilerOptionPaths = computeCompilerOptionsPaths(
|
||||
options.tsConfig,
|
||||
@ -196,11 +199,20 @@ function createRollupOptions(
|
||||
preferBuiltins: true,
|
||||
extensions: fileExtensions,
|
||||
}),
|
||||
babel({
|
||||
...createBabelConfig(options, options.projectRoot),
|
||||
getBabelInputPlugin({
|
||||
// TODO(jack): Remove this in Nx 10
|
||||
...legacyCreateBabelConfig(options, options.projectRoot),
|
||||
|
||||
cwd: join(context.workspaceRoot, sourceRoot),
|
||||
rootMode: 'upward',
|
||||
babelrc: true,
|
||||
extensions: fileExtensions,
|
||||
externalHelpers: false,
|
||||
exclude: 'node_modules/**',
|
||||
babelHelpers: 'bundled',
|
||||
exclude: /node_modules/,
|
||||
plugins: [
|
||||
'babel-plugin-transform-async-to-promises',
|
||||
['@babel/plugin-transform-regenerator', { async: false }],
|
||||
],
|
||||
}),
|
||||
commonjs(),
|
||||
filesize(),
|
||||
@ -237,45 +249,46 @@ function createRollupOptions(
|
||||
: rollupConfig;
|
||||
}
|
||||
|
||||
function createBabelConfig(
|
||||
function legacyCreateBabelConfig(
|
||||
options: PackageBuilderOptions,
|
||||
projectRoot: string
|
||||
) {
|
||||
let babelConfig: any = _createBabelConfig(projectRoot, false, false);
|
||||
if (options.babelConfig) {
|
||||
let babelConfig: any = createBabelConfig(projectRoot, false, false);
|
||||
babelConfig = require(options.babelConfig)(babelConfig, options);
|
||||
// Ensure async functions are transformed to promises properly.
|
||||
upsert(
|
||||
'plugins',
|
||||
'babel-plugin-transform-async-to-promises',
|
||||
null,
|
||||
babelConfig
|
||||
);
|
||||
upsert(
|
||||
'plugins',
|
||||
'@babel/plugin-transform-regenerator',
|
||||
{ async: false },
|
||||
babelConfig
|
||||
);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
// Ensure async functions are transformed to promises properly.
|
||||
upsert(
|
||||
'plugins',
|
||||
'babel-plugin-transform-async-to-promises',
|
||||
null,
|
||||
babelConfig
|
||||
);
|
||||
upsert(
|
||||
'plugins',
|
||||
'@babel/plugin-transform-regenerator',
|
||||
{ async: false },
|
||||
babelConfig
|
||||
);
|
||||
return babelConfig;
|
||||
}
|
||||
|
||||
function upsert(
|
||||
type: 'presets' | 'plugins',
|
||||
pluginOrPreset: string,
|
||||
opts: null | JsonObject,
|
||||
config: any
|
||||
) {
|
||||
if (
|
||||
!config[type].some(
|
||||
(p) =>
|
||||
(Array.isArray(p) && p[0].indexOf(pluginOrPreset) !== -1) ||
|
||||
p.indexOf(pluginOrPreset) !== -1
|
||||
)
|
||||
function upsert(
|
||||
type: 'presets' | 'plugins',
|
||||
pluginOrPreset: string,
|
||||
opts: null | JsonObject,
|
||||
config: any
|
||||
) {
|
||||
const fullPath = require.resolve(pluginOrPreset);
|
||||
config[type] = config[type].concat([opts ? [fullPath, opts] : fullPath]);
|
||||
if (
|
||||
!config[type].some(
|
||||
(p) =>
|
||||
(Array.isArray(p) && p[0].indexOf(pluginOrPreset) !== -1) ||
|
||||
p.indexOf(pluginOrPreset) !== -1
|
||||
)
|
||||
) {
|
||||
const fullPath = require.resolve(pluginOrPreset);
|
||||
config[type] = config[type].concat([opts ? [fullPath, opts] : fullPath]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
},
|
||||
"babelConfig": {
|
||||
"type": "string",
|
||||
"description": "Path to a function which takes a babel config and returns an updated babel config"
|
||||
"description": "(deprecated) Path to a function which takes a babel config and returns an updated babel config"
|
||||
},
|
||||
"umdName": {
|
||||
"type": "string",
|
||||
|
||||
@ -0,0 +1 @@
|
||||
{}
|
||||
@ -48,6 +48,46 @@ describe('init', () => {
|
||||
},
|
||||
tree
|
||||
);
|
||||
expect(result.exists('jest.config.js')).toEqual(false);
|
||||
expect(result.exists('jest.config.js')).toBe(false);
|
||||
});
|
||||
|
||||
describe('babel config', () => {
|
||||
it('should create babel config if not present', async () => {
|
||||
const result = await runSchematic(
|
||||
'init',
|
||||
{
|
||||
unitTestRunner: 'none',
|
||||
},
|
||||
tree
|
||||
);
|
||||
expect(result.exists('babel.config.json')).toBe(true);
|
||||
});
|
||||
|
||||
it('should not overwrite existing babel config', async () => {
|
||||
tree.create('babel.config.json', '{ "preset": ["preset-awesome"] }');
|
||||
|
||||
const result = await runSchematic(
|
||||
'init',
|
||||
{
|
||||
unitTestRunner: 'none',
|
||||
},
|
||||
tree
|
||||
);
|
||||
|
||||
const existing = result.read('babel.config.json').toString();
|
||||
expect(existing).toMatch('{ "preset": ["preset-awesome"] }');
|
||||
});
|
||||
|
||||
it('should not overwrite existing babel config (.js)', async () => {
|
||||
tree.create('/babel.config.js', 'module.exports = () => {};');
|
||||
const result = await runSchematic(
|
||||
'init',
|
||||
{
|
||||
unitTestRunner: 'none',
|
||||
},
|
||||
tree
|
||||
);
|
||||
expect(result.exists('babel.config.json')).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { chain, noop, Rule } from '@angular-devkit/schematics';
|
||||
import { chain, noop, Rule, Tree } from '@angular-devkit/schematics';
|
||||
import {
|
||||
addPackageWithInit,
|
||||
formatFiles,
|
||||
@ -10,6 +10,7 @@ import {
|
||||
documentRegisterElementVersion,
|
||||
nxVersion,
|
||||
} from '../../utils/versions';
|
||||
import { initRootBabelConfig } from '../../utils/rules';
|
||||
|
||||
function updateDependencies(): Rule {
|
||||
return updateJsonInTree('package.json', (json) => {
|
||||
@ -36,6 +37,7 @@ export default function (schema: Schema) {
|
||||
? addPackageWithInit('@nrwl/cypress')
|
||||
: noop(),
|
||||
updateDependencies(),
|
||||
initRootBabelConfig(),
|
||||
formatFiles(schema),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
/** @deprecated We no longer use this function and will be removed in Nx 10. */
|
||||
// TODO(jack): Remove this in Nx 10
|
||||
export function createBabelConfig(
|
||||
context: string,
|
||||
esm: boolean,
|
||||
|
||||
@ -5,6 +5,7 @@ import { LicenseWebpackPlugin } from 'license-webpack-plugin';
|
||||
import TsConfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
|
||||
import { ProgressPlugin } from 'webpack';
|
||||
import { BuildBuilderOptions } from './types';
|
||||
import { normalize } from '@angular-devkit/core';
|
||||
import CircularDependencyPlugin = require('circular-dependency-plugin');
|
||||
import ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||
|
||||
@ -19,6 +20,7 @@ describe('getBaseWebpackPartial', () => {
|
||||
tsConfig: 'tsconfig.json',
|
||||
fileReplacements: [],
|
||||
root: '/root',
|
||||
sourceRoot: normalize('/root/src'),
|
||||
statsJson: false,
|
||||
};
|
||||
(<any>(
|
||||
@ -164,12 +166,8 @@ describe('getBaseWebpackPartial', () => {
|
||||
|
||||
expect(
|
||||
(result.module.rules.find((rule) => rule.loader === 'babel-loader')
|
||||
.options as any).presets.find(
|
||||
(p) => p[0].indexOf('@babel/preset-env') !== -1
|
||||
)[1]
|
||||
).toMatchObject({
|
||||
targets: { esmodules: true },
|
||||
});
|
||||
.options as any).envName
|
||||
).toMatch('modern');
|
||||
});
|
||||
|
||||
it('should not override preset-env target for es5', () => {
|
||||
@ -177,12 +175,8 @@ describe('getBaseWebpackPartial', () => {
|
||||
|
||||
expect(
|
||||
(result.module.rules.find((rule) => rule.loader === 'babel-loader')
|
||||
.options as any).presets.find(
|
||||
(p) => p[0].indexOf('@babel/preset-env') !== -1
|
||||
)[1]
|
||||
).toMatchObject({
|
||||
targets: undefined,
|
||||
});
|
||||
.options as any).envName
|
||||
).toMatch('legacy');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import * as webpack from 'webpack';
|
||||
import { Configuration, ProgressPlugin, Stats } from 'webpack';
|
||||
import { dirname, resolve } from 'path';
|
||||
import { join, resolve } from 'path';
|
||||
import { LicenseWebpackPlugin } from 'license-webpack-plugin';
|
||||
import * as CopyWebpackPlugin from 'copy-webpack-plugin';
|
||||
import * as TerserWebpackPlugin from 'terser-webpack-plugin';
|
||||
@ -8,7 +8,6 @@ import TsConfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
|
||||
|
||||
import { AssetGlobPattern, BuildBuilderOptions } from './types';
|
||||
import { getOutputHashFormat } from './hash-format';
|
||||
import { createBabelConfig } from './babel-config';
|
||||
import CircularDependencyPlugin = require('circular-dependency-plugin');
|
||||
import ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||
|
||||
@ -52,7 +51,10 @@ export function getBaseWebpackPartial(
|
||||
loader: `babel-loader`,
|
||||
exclude: /node_modules/,
|
||||
options: {
|
||||
...createBabelConfig(dirname(options.main), esm, options.verbose),
|
||||
rootMode: 'upward',
|
||||
cwd: join(options.root, options.sourceRoot),
|
||||
envName: esm ? 'modern' : 'legacy',
|
||||
babelrc: true,
|
||||
cacheDirectory: true,
|
||||
cacheCompression: false,
|
||||
},
|
||||
@ -153,7 +155,8 @@ export function createTerserPlugin(esm: boolean, sourceMap: boolean) {
|
||||
cache: true,
|
||||
sourceMap,
|
||||
terserOptions: {
|
||||
ecma: esm ? 6 : 5,
|
||||
ecma: esm ? 8 : 5,
|
||||
// Don't remove safari 10 workaround for ES modules
|
||||
safari10: true,
|
||||
output: {
|
||||
ascii_only: true,
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import { getDevServerConfig } from './devserver.config';
|
||||
import { Logger } from '@angular-devkit/core/src/logger';
|
||||
jest.mock('tsconfig-paths-webpack-plugin');
|
||||
import TsConfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
|
||||
import * as ts from 'typescript';
|
||||
import * as fs from 'fs';
|
||||
import { WebBuildBuilderOptions } from '../builders/build/build.impl';
|
||||
import { WebDevServerOptions } from '../builders/dev-server/dev-server.impl';
|
||||
import { join } from 'path';
|
||||
|
||||
jest.mock('tsconfig-paths-webpack-plugin');
|
||||
import ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||
|
||||
describe('getDevServerConfig', () => {
|
||||
@ -18,6 +19,8 @@ describe('getDevServerConfig', () => {
|
||||
let sourceRoot: string;
|
||||
|
||||
beforeEach(() => {
|
||||
root = join(__dirname, '../../../..');
|
||||
sourceRoot = join(root, 'apps/app');
|
||||
buildInput = {
|
||||
main: 'main.ts',
|
||||
index: 'index.html',
|
||||
@ -39,9 +42,9 @@ describe('getDevServerConfig', () => {
|
||||
outputPath: 'dist',
|
||||
tsConfig: 'tsconfig.json',
|
||||
fileReplacements: [],
|
||||
root,
|
||||
sourceRoot,
|
||||
};
|
||||
root = join(__dirname, '../../../..');
|
||||
sourceRoot = join(root, 'apps/app');
|
||||
|
||||
serveInput = {
|
||||
host: 'localhost',
|
||||
|
||||
@ -47,6 +47,8 @@ export function normalizeBuildOptions<T extends BuildBuilderOptions>(
|
||||
): T {
|
||||
return {
|
||||
...options,
|
||||
root,
|
||||
sourceRoot,
|
||||
main: resolve(root, options.main),
|
||||
outputPath: resolve(root, options.outputPath),
|
||||
tsConfig: resolve(root, options.tsConfig),
|
||||
|
||||
19
packages/web/src/utils/rules.ts
Normal file
19
packages/web/src/utils/rules.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { Rule, Tree } from '@angular-devkit/schematics';
|
||||
|
||||
export function initRootBabelConfig(): Rule {
|
||||
return (host: Tree) => {
|
||||
if (host.exists('/babel.config.json') || host.exists('/babel.config.js'))
|
||||
return;
|
||||
host.create(
|
||||
'/babel.config.json',
|
||||
JSON.stringify(
|
||||
{
|
||||
presets: ['@nrwl/web/babel'],
|
||||
babelrcRoots: ['*'], // Make sure .babelrc files other than root can be loaded in a monorepo
|
||||
},
|
||||
null,
|
||||
2
|
||||
)
|
||||
);
|
||||
};
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
import { FileReplacement } from './normalize';
|
||||
import { JsonObject, Path } from '@angular-devkit/core';
|
||||
import { JsonObject } from '@angular-devkit/core';
|
||||
|
||||
export interface OptimizationOptions {
|
||||
scripts: boolean;
|
||||
@ -37,7 +37,7 @@ export interface BuildBuilderOptions {
|
||||
webpackConfig?: string;
|
||||
|
||||
root?: string;
|
||||
sourceRoot?: Path;
|
||||
sourceRoot?: string;
|
||||
}
|
||||
|
||||
export interface Globals {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { getWebConfig as getWebPartial } from './web.config';
|
||||
jest.mock('tsconfig-paths-webpack-plugin');
|
||||
import TsConfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
|
||||
import { createConsoleLogger } from '@angular-devkit/core/node';
|
||||
import { Logger } from '@angular-devkit/core/src/logger';
|
||||
@ -7,6 +6,8 @@ import * as ts from 'typescript';
|
||||
import { WebBuildBuilderOptions } from '../builders/build/build.impl';
|
||||
import { join } from 'path';
|
||||
|
||||
jest.mock('tsconfig-paths-webpack-plugin');
|
||||
|
||||
describe('getWebConfig', () => {
|
||||
let input: WebBuildBuilderOptions;
|
||||
let logger: Logger;
|
||||
@ -15,6 +16,8 @@ describe('getWebConfig', () => {
|
||||
let mockCompilerOptions: any;
|
||||
|
||||
beforeEach(() => {
|
||||
root = join(__dirname, '../../../..');
|
||||
sourceRoot = join(root, 'apps/app');
|
||||
input = {
|
||||
main: 'main.ts',
|
||||
index: 'index.html',
|
||||
@ -36,9 +39,9 @@ describe('getWebConfig', () => {
|
||||
outputPath: 'dist',
|
||||
tsConfig: 'tsconfig.json',
|
||||
fileReplacements: [],
|
||||
root,
|
||||
sourceRoot,
|
||||
};
|
||||
root = join(__dirname, '../../../..');
|
||||
sourceRoot = join(root, 'apps/app');
|
||||
logger = createConsoleLogger();
|
||||
|
||||
mockCompilerOptions = {
|
||||
|
||||
@ -6,16 +6,16 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {
|
||||
Rule,
|
||||
Tree,
|
||||
SchematicContext,
|
||||
DirEntry,
|
||||
noop,
|
||||
chain,
|
||||
Source,
|
||||
mergeWith,
|
||||
apply,
|
||||
chain,
|
||||
DirEntry,
|
||||
forEach,
|
||||
mergeWith,
|
||||
noop,
|
||||
Rule,
|
||||
SchematicContext,
|
||||
Source,
|
||||
Tree,
|
||||
} from '@angular-devkit/schematics';
|
||||
import * as ts from 'typescript';
|
||||
import * as stripJsonComments from 'strip-json-comments';
|
||||
@ -395,6 +395,10 @@ export function readJsonInTree<T = any>(host: Tree, path: string): T {
|
||||
* Method for utilizing the project graph in schematics
|
||||
*/
|
||||
export function getProjectGraphFromHost(host: Tree): ProjectGraph {
|
||||
return onlyWorkspaceProjects(getFullProjectGraphFromHost(host));
|
||||
}
|
||||
|
||||
export function getFullProjectGraphFromHost(host: Tree): ProjectGraph {
|
||||
const workspaceJson = readJsonInTree(host, getWorkspacePath(host));
|
||||
const nxJson = readJsonInTree<NxJson>(host, '/nx.json');
|
||||
|
||||
@ -425,8 +429,12 @@ export function getProjectGraphFromHost(host: Tree): ProjectGraph {
|
||||
);
|
||||
});
|
||||
|
||||
return onlyWorkspaceProjects(
|
||||
createProjectGraph(workspaceJson, nxJson, workspaceFiles, fileRead, false)
|
||||
return createProjectGraph(
|
||||
workspaceJson,
|
||||
nxJson,
|
||||
workspaceFiles,
|
||||
fileRead,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -59,8 +59,6 @@ function checkFiles(files: string[]) {
|
||||
r.package
|
||||
)} has new version ${chalk.bold(r.latest)} (current: ${r.prev})`
|
||||
);
|
||||
} else {
|
||||
console.log(`${logContext} ✔️ ${r.package} is update to date`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
2
test.ts
2
test.ts
@ -1,5 +1,5 @@
|
||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||
import 'core-js/es7/reflect';
|
||||
import 'core-js/proposals/reflect-metadata';
|
||||
import 'zone.js/dist/zone';
|
||||
import 'zone.js/dist/zone-testing';
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user