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`
|
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
|
### entryFile
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@ List of static assets.
|
|||||||
|
|
||||||
Type: `string`
|
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
|
### entryFile
|
||||||
|
|
||||||
|
|||||||
@ -199,7 +199,7 @@ forEachCli((currentCLIName) => {
|
|||||||
);
|
);
|
||||||
}, 120000);
|
}, 120000);
|
||||||
|
|
||||||
xit('should be able to use babel-jest', async () => {
|
it('should be able to use babel-jest', async () => {
|
||||||
ensureProject();
|
ensureProject();
|
||||||
const appName = uniq('app');
|
const appName = uniq('app');
|
||||||
const libName = uniq('lib');
|
const libName = uniq('lib');
|
||||||
@ -211,11 +211,6 @@ forEachCli((currentCLIName) => {
|
|||||||
`generate @nrwl/react:lib ${libName} --no-interactive --babelJest`
|
`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}`);
|
const appTestResults = await runCLIAsync(`test ${appName}`);
|
||||||
expect(appTestResults.stderr).toContain('Test Suites: 1 passed, 1 total');
|
expect(appTestResults.stderr).toContain('Test Suites: 1 passed, 1 total');
|
||||||
|
|
||||||
@ -308,7 +303,7 @@ forEachCli((currentCLIName) => {
|
|||||||
}
|
}
|
||||||
checkFilesExist(...filesToCheck);
|
checkFilesExist(...filesToCheck);
|
||||||
expect(readFile(`dist/apps/${appName}/main.js`)).toContain(
|
expect(readFile(`dist/apps/${appName}/main.js`)).toContain(
|
||||||
'var App = () => {'
|
'const App = () =>'
|
||||||
);
|
);
|
||||||
runCLI(`build ${appName} --prod --output-hashing none`);
|
runCLI(`build ${appName} --prod --output-hashing none`);
|
||||||
filesToCheck = [
|
filesToCheck = [
|
||||||
|
|||||||
@ -175,7 +175,7 @@ export function newProject(): void {
|
|||||||
`@nrwl/storybook`,
|
`@nrwl/storybook`,
|
||||||
`@nrwl/nx-plugin`,
|
`@nrwl/nx-plugin`,
|
||||||
];
|
];
|
||||||
yarnAdd(packages.join(` `));
|
yarnAdd([`@nrwl/eslint-plugin-nx`].concat(packages).join(` `));
|
||||||
packages
|
packages
|
||||||
.filter((f) => f != '@nrwl/nx-plugin')
|
.filter((f) => f != '@nrwl/nx-plugin')
|
||||||
.forEach((p) => {
|
.forEach((p) => {
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { stripIndents } from '@angular-devkit/core/src/utils/literals';
|
|
||||||
import {
|
import {
|
||||||
checkFilesExist,
|
checkFilesExist,
|
||||||
ensureProject,
|
ensureProject,
|
||||||
@ -6,7 +5,6 @@ import {
|
|||||||
readFile,
|
readFile,
|
||||||
runCLI,
|
runCLI,
|
||||||
runCLIAsync,
|
runCLIAsync,
|
||||||
supportUi,
|
|
||||||
uniq,
|
uniq,
|
||||||
updateFile,
|
updateFile,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
@ -54,72 +52,9 @@ forEachCli((currentCLIName) => {
|
|||||||
const lintE2eResults = runCLI(`lint ${appName}-e2e`);
|
const lintE2eResults = runCLI(`lint ${appName}-e2e`);
|
||||||
expect(lintE2eResults).toContain('All files pass linting.');
|
expect(lintE2eResults).toContain('All files pass linting.');
|
||||||
|
|
||||||
if (supportUi()) {
|
const e2eResults = runCLI(`e2e ${appName}-e2e`);
|
||||||
const e2eResults = runCLI(`e2e ${appName}-e2e`);
|
expect(e2eResults).toContain('All specs passed!');
|
||||||
expect(e2eResults).toContain('All specs passed!');
|
|
||||||
}
|
|
||||||
}, 120000);
|
}, 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', () => {
|
describe('CLI - Environment Variables', () => {
|
||||||
@ -140,7 +75,7 @@ forEachCli((currentCLIName) => {
|
|||||||
env: { ...process.env, NODE_ENV: 'test', NX_BUILD: '52', NX_API: 'QA' },
|
env: { ...process.env, NODE_ENV: 'test', NX_BUILD: '52', NX_API: 'QA' },
|
||||||
});
|
});
|
||||||
expect(readFile(`dist/apps/${appName}/main.js`)).toContain(
|
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/router": "^9.1.0",
|
||||||
"@angular/service-worker": "^9.1.0",
|
"@angular/service-worker": "^9.1.0",
|
||||||
"@angular/upgrade": "^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-class-properties": "7.8.3",
|
||||||
"@babel/plugin-proposal-decorators": "7.8.3",
|
"@babel/plugin-proposal-decorators": "7.8.3",
|
||||||
"@babel/plugin-transform-regenerator": "7.8.3",
|
"@babel/plugin-transform-regenerator": "7.8.7",
|
||||||
"@babel/preset-env": "7.8.4",
|
"@babel/preset-typescript": "7.9.0",
|
||||||
"@babel/preset-react": "7.8.3",
|
"@babel/preset-react": "7.9.4",
|
||||||
"@babel/preset-typescript": "7.8.3",
|
|
||||||
"@bazel/bazel": "^1.2.0",
|
"@bazel/bazel": "^1.2.0",
|
||||||
"@bazel/ibazel": "^0.10.3",
|
"@bazel/ibazel": "^0.10.3",
|
||||||
"@cypress/webpack-preprocessor": "^4.1.2",
|
"@cypress/webpack-preprocessor": "^4.1.2",
|
||||||
@ -73,6 +73,7 @@
|
|||||||
"@ngrx/store-devtools": "9.1.0",
|
"@ngrx/store-devtools": "9.1.0",
|
||||||
"@ngtools/webpack": "~9.1.0",
|
"@ngtools/webpack": "~9.1.0",
|
||||||
"@reduxjs/toolkit": "1.3.2",
|
"@reduxjs/toolkit": "1.3.2",
|
||||||
|
"@rollup/plugin-babel": "5.0.2",
|
||||||
"@rollup/plugin-commonjs": "11.0.2",
|
"@rollup/plugin-commonjs": "11.0.2",
|
||||||
"@rollup/plugin-image": "2.0.4",
|
"@rollup/plugin-image": "2.0.4",
|
||||||
"@rollup/plugin-node-resolve": "7.1.1",
|
"@rollup/plugin-node-resolve": "7.1.1",
|
||||||
@ -110,12 +111,12 @@
|
|||||||
"app-root-path": "^2.0.1",
|
"app-root-path": "^2.0.1",
|
||||||
"autoprefixer": "9.7.4",
|
"autoprefixer": "9.7.4",
|
||||||
"axios": "^0.19.0",
|
"axios": "^0.19.0",
|
||||||
"babel-loader": "8.0.6",
|
"babel-loader": "8.1.0",
|
||||||
"babel-plugin-const-enum": "^0.0.5",
|
"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-emotion": "^10.0.29",
|
||||||
"babel-plugin-macros": "2.6.1",
|
|
||||||
"babel-plugin-styled-components": "^1.10.7",
|
"babel-plugin-styled-components": "^1.10.7",
|
||||||
"babel-plugin-transform-async-to-promises": "0.8.15",
|
|
||||||
"browserslist": "4.8.7",
|
"browserslist": "4.8.7",
|
||||||
"cacache": "12.0.2",
|
"cacache": "12.0.2",
|
||||||
"caniuse-lite": "^1.0.30001030",
|
"caniuse-lite": "^1.0.30001030",
|
||||||
@ -126,7 +127,7 @@
|
|||||||
"confusing-browser-globals": "^1.0.9",
|
"confusing-browser-globals": "^1.0.9",
|
||||||
"conventional-changelog-cli": "^2.0.23",
|
"conventional-changelog-cli": "^2.0.23",
|
||||||
"copy-webpack-plugin": "5.1.1",
|
"copy-webpack-plugin": "5.1.1",
|
||||||
"core-js": "^2.6.9",
|
"core-js": "^3.6.5",
|
||||||
"cosmiconfig": "^4.0.0",
|
"cosmiconfig": "^4.0.0",
|
||||||
"css-loader": "3.4.2",
|
"css-loader": "3.4.2",
|
||||||
"cypress": "^4.1.0",
|
"cypress": "^4.1.0",
|
||||||
@ -197,7 +198,6 @@
|
|||||||
"regenerator-runtime": "0.13.3",
|
"regenerator-runtime": "0.13.3",
|
||||||
"release-it": "^7.4.0",
|
"release-it": "^7.4.0",
|
||||||
"rollup": "1.31.1",
|
"rollup": "1.31.1",
|
||||||
"rollup-plugin-babel": "4.3.3",
|
|
||||||
"rollup-plugin-copy": "3.3.0",
|
"rollup-plugin-copy": "3.3.0",
|
||||||
"rollup-plugin-filesize": "6.2.1",
|
"rollup-plugin-filesize": "6.2.1",
|
||||||
"rollup-plugin-local-resolve": "1.0.7",
|
"rollup-plugin-local-resolve": "1.0.7",
|
||||||
|
|||||||
@ -23,7 +23,6 @@ describe('init', () => {
|
|||||||
expect(dependencies['@angular/platform-browser']).toBeDefined();
|
expect(dependencies['@angular/platform-browser']).toBeDefined();
|
||||||
expect(dependencies['@angular/platform-browser-dynamic']).toBeDefined();
|
expect(dependencies['@angular/platform-browser-dynamic']).toBeDefined();
|
||||||
expect(dependencies['@angular/router']).toBeDefined();
|
expect(dependencies['@angular/router']).toBeDefined();
|
||||||
expect(dependencies['core-js']).toBeDefined();
|
|
||||||
expect(dependencies['rxjs']).toBeDefined();
|
expect(dependencies['rxjs']).toBeDefined();
|
||||||
expect(dependencies['zone.js']).toBeDefined();
|
expect(dependencies['zone.js']).toBeDefined();
|
||||||
expect(devDependencies['@angular/compiler-cli']).toBeDefined();
|
expect(devDependencies['@angular/compiler-cli']).toBeDefined();
|
||||||
|
|||||||
@ -34,7 +34,6 @@ const updateDependencies = addDepsToPackageJson(
|
|||||||
'@angular/platform-browser': angularVersion,
|
'@angular/platform-browser': angularVersion,
|
||||||
'@angular/platform-browser-dynamic': angularVersion,
|
'@angular/platform-browser-dynamic': angularVersion,
|
||||||
'@angular/router': angularVersion,
|
'@angular/router': angularVersion,
|
||||||
'core-js': '^2.5.4',
|
|
||||||
rxjs: rxjsVersion,
|
rxjs: rxjsVersion,
|
||||||
'zone.js': '^0.10.2',
|
'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
|
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||||
<% if (isLibrary) { %>
|
<% if (isLibrary) { %>
|
||||||
import 'core-js/es7/reflect';
|
|
||||||
import 'zone.js/dist/zone';
|
import 'zone.js/dist/zone';
|
||||||
<% } %>
|
<% } %>
|
||||||
import 'zone.js/dist/zone-testing';
|
import 'zone.js/dist/zone-testing';
|
||||||
|
|||||||
@ -135,7 +135,6 @@ module.exports = function(config) {
|
|||||||
appTree
|
appTree
|
||||||
);
|
);
|
||||||
const testTs = resultTree.read('libs/lib1/src/test.ts').toString();
|
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';");
|
expect(testTs).toContain("import 'zone.js/dist/zone';");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -199,7 +198,6 @@ module.exports = function(config) {
|
|||||||
appTree
|
appTree
|
||||||
);
|
);
|
||||||
const testTs = resultTree.read('apps/app1/src/test.ts').toString();
|
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';");
|
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', () => {
|
describe('--setup-file', () => {
|
||||||
it('should generate src/test-setup.ts', async () => {
|
it('should generate src/test-setup.ts', async () => {
|
||||||
const resultTree = await runSchematic(
|
const resultTree = await runSchematic(
|
||||||
|
|||||||
@ -3,8 +3,8 @@ export const jestVersion = '25.2.3';
|
|||||||
export const jestTypesVersion = '25.1.4';
|
export const jestTypesVersion = '25.1.4';
|
||||||
export const tsJestVersion = '25.2.1';
|
export const tsJestVersion = '25.2.1';
|
||||||
|
|
||||||
export const babelCoreVersion = '7.8.4';
|
export const babelCoreVersion = '7.9.6';
|
||||||
export const babelPresetEnvVersion = '7.8.4';
|
export const babelPresetEnvVersion = '7.9.6';
|
||||||
export const babelPresetTypescriptVersion = '7.8.3';
|
export const babelPresetTypescriptVersion = '7.9.0';
|
||||||
export const babelPresetReactVersion = '7.8.3';
|
export const babelPresetReactVersion = '7.9.4';
|
||||||
export const babelJestVersion = '25.1.0';
|
export const babelJestVersion = '25.1.0';
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"presets": ["next/babel"],
|
"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",
|
"version": "8.12.0-beta.1",
|
||||||
"description": "Ensure React correct webpack config and babel preset",
|
"description": "Ensure React correct webpack config and babel preset",
|
||||||
"factory": "./src/migrations/update-8-12-0/fix-react-files-8-12-0"
|
"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": {
|
"packageJsonUpdates": {
|
||||||
@ -181,6 +191,79 @@
|
|||||||
"alwaysAddToPackageJson": false
|
"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": "*"
|
"@nrwl/workspace": "*"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "^7.8.4",
|
"@babel/core": "7.9.6",
|
||||||
"@babel/preset-react": "^7.8.3",
|
"@babel/preset-react": "7.9.4",
|
||||||
"@nrwl/cypress": "*",
|
"@nrwl/cypress": "*",
|
||||||
"@nrwl/jest": "*",
|
"@nrwl/jest": "*",
|
||||||
"@nrwl/web": "*",
|
"@nrwl/web": "*",
|
||||||
"@angular-devkit/schematics": "~9.1.0",
|
"@angular-devkit/schematics": "~9.1.0",
|
||||||
"@svgr/webpack": "^5.2.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",
|
"confusing-browser-globals": "^1.0.9",
|
||||||
"eslint-plugin-import": "^2.20.1",
|
"eslint-plugin-import": "^2.20.1",
|
||||||
"eslint-plugin-jsx-a11y": "^6.2.3",
|
"eslint-plugin-jsx-a11y": "^6.2.3",
|
||||||
|
|||||||
@ -1,12 +1,7 @@
|
|||||||
import { Configuration } from 'webpack';
|
import { Configuration } from 'webpack';
|
||||||
import { updateBabelOptions } from '../src/utils/babel-utils';
|
|
||||||
|
|
||||||
// Add React-specific configuration
|
// Add React-specific configuration
|
||||||
function getWebpackConfig(config: 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(
|
config.module.rules.push(
|
||||||
{
|
{
|
||||||
test: /\.(png|jpe?g|gif|webp)$/,
|
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 { Tree } from '@angular-devkit/schematics';
|
||||||
import { createEmptyWorkspace } from '@nrwl/workspace/testing';
|
import { createEmptyWorkspace } from '@nrwl/workspace/testing';
|
||||||
import * as stripJsonComments from 'strip-json-comments';
|
import * as stripJsonComments from 'strip-json-comments';
|
||||||
import { readJsonInTree, NxJson } from '@nrwl/workspace';
|
import { NxJson, readJsonInTree } from '@nrwl/workspace';
|
||||||
import { runSchematic } from '../../utils/testing';
|
import { runSchematic } from '../../utils/testing';
|
||||||
|
|
||||||
describe('app', () => {
|
describe('app', () => {
|
||||||
@ -44,6 +44,7 @@ describe('app', () => {
|
|||||||
|
|
||||||
it('should generate files', async () => {
|
it('should generate files', async () => {
|
||||||
const tree = await runSchematic('app', { name: 'myApp' }, appTree);
|
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/main.tsx')).toBeTruthy();
|
||||||
expect(tree.exists('apps/my-app/src/app/app.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();
|
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 {
|
import {
|
||||||
apply,
|
|
||||||
chain,
|
chain,
|
||||||
externalSchematic,
|
|
||||||
filter,
|
|
||||||
mergeWith,
|
|
||||||
move,
|
|
||||||
noop,
|
|
||||||
Rule,
|
Rule,
|
||||||
SchematicContext,
|
SchematicContext,
|
||||||
template,
|
|
||||||
Tree,
|
Tree,
|
||||||
url,
|
|
||||||
} from '@angular-devkit/schematics';
|
} from '@angular-devkit/schematics';
|
||||||
import {
|
import { addLintFiles, formatFiles } from '@nrwl/workspace';
|
||||||
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 { extraEslintDependencies, reactEslintJson } from '../../utils/lint';
|
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 init from '../init/init';
|
||||||
import { Schema } from './schema';
|
import { Schema } from './schema';
|
||||||
|
import { createApplicationFiles } from './lib/create-application-files';
|
||||||
interface NormalizedSchema extends Schema {
|
import { updateJestConfig } from './lib/update-jest-config';
|
||||||
projectName: string;
|
import { normalizeOptions } from './lib/normalize-options';
|
||||||
appProjectRoot: Path;
|
import { addProject } from './lib/add-project';
|
||||||
e2eProjectName: string;
|
import { addCypress } from './lib/add-cypress';
|
||||||
parsedTags: string[];
|
import { addJest } from './lib/add-jest';
|
||||||
fileName: string;
|
import { addRouting } from './lib/add-routing';
|
||||||
styledModule: null | string;
|
import { setDefaults } from './lib/set-defaults';
|
||||||
hasStyles: boolean;
|
import { updateNxJson } from './lib/update-nx-json';
|
||||||
}
|
import { addStyledModuleDependencies } from '../../rules/add-styled-dependencies';
|
||||||
|
|
||||||
export default function (schema: Schema): Rule {
|
export default function (schema: Schema): Rule {
|
||||||
return (host: Tree, context: SchematicContext) => {
|
return (host: Tree, context: SchematicContext) => {
|
||||||
const options = normalizeOptions(host, schema);
|
const options = normalizeOptions(host, schema);
|
||||||
|
|
||||||
return chain([
|
return chain([
|
||||||
init({
|
init({
|
||||||
...options,
|
...options,
|
||||||
@ -73,283 +37,10 @@ export default function (schema: Schema): Rule {
|
|||||||
addCypress(options),
|
addCypress(options),
|
||||||
addJest(options),
|
addJest(options),
|
||||||
updateJestConfig(options),
|
updateJestConfig(options),
|
||||||
addStyledModuleDependencies(options),
|
addStyledModuleDependencies(options.styledModule),
|
||||||
addRouting(options, context),
|
addRouting(options, context),
|
||||||
setDefaults(options),
|
setDefaults(options),
|
||||||
formatFiles(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 { Linter } from '@nrwl/workspace';
|
||||||
import { SupportedStyles } from 'packages/react/typings/style';
|
import { SupportedStyles } from 'packages/react/typings/style';
|
||||||
|
import { Path } from '@angular-devkit/core';
|
||||||
|
|
||||||
export interface Schema {
|
export interface Schema {
|
||||||
name: string;
|
name: string;
|
||||||
@ -17,3 +18,13 @@ export interface Schema {
|
|||||||
skipWorkspaceJson?: boolean;
|
skipWorkspaceJson?: boolean;
|
||||||
js?: 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,
|
getProjectConfig,
|
||||||
insert,
|
insert,
|
||||||
} from '@nrwl/workspace/src/utils/ast-utils';
|
} from '@nrwl/workspace/src/utils/ast-utils';
|
||||||
import { CSS_IN_JS_DEPENDENCIES } from '../../utils/styled';
|
|
||||||
import {
|
import {
|
||||||
typesReactRouterDomVersion,
|
|
||||||
reactRouterDomVersion,
|
reactRouterDomVersion,
|
||||||
|
typesReactRouterDomVersion,
|
||||||
} from '../../utils/versions';
|
} from '../../utils/versions';
|
||||||
import { assertValidStyle } from '../../utils/assertion';
|
import { assertValidStyle } from '../../utils/assertion';
|
||||||
import { toJS } from '@nrwl/workspace/src/utils/rules/to-js';
|
import { toJS } from '@nrwl/workspace/src/utils/rules/to-js';
|
||||||
|
import { addStyledModuleDependencies } from '../../rules/add-styled-dependencies';
|
||||||
|
|
||||||
interface NormalizedSchema extends Schema {
|
interface NormalizedSchema extends Schema {
|
||||||
projectSourceRoot: Path;
|
projectSourceRoot: Path;
|
||||||
@ -42,7 +42,7 @@ export default function (schema: Schema): Rule {
|
|||||||
const options = await normalizeOptions(host, schema, context);
|
const options = await normalizeOptions(host, schema, context);
|
||||||
return chain([
|
return chain([
|
||||||
createComponentFiles(options),
|
createComponentFiles(options),
|
||||||
addStyledModuleDependencies(options),
|
addStyledModuleDependencies(options.styledModule),
|
||||||
addExportsToBarrel(options),
|
addExportsToBarrel(options),
|
||||||
options.routing
|
options.routing
|
||||||
? addDepsToPackageJson(
|
? 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 {
|
function addExportsToBarrel(options: NormalizedSchema): Rule {
|
||||||
return async (host: Tree) => {
|
return async (host: Tree) => {
|
||||||
const workspace = await getWorkspace(host);
|
const workspace = await getWorkspace(host);
|
||||||
@ -95,6 +84,7 @@ function addExportsToBarrel(options: NormalizedSchema): Rule {
|
|||||||
options.projectSourceRoot,
|
options.projectSourceRoot,
|
||||||
options.js ? 'index.js' : 'index.ts'
|
options.js ? 'index.js' : 'index.ts'
|
||||||
);
|
);
|
||||||
|
console.log('index', indexFilePath);
|
||||||
const buffer = host.read(indexFilePath);
|
const buffer = host.read(indexFilePath);
|
||||||
if (!!buffer) {
|
if (!!buffer) {
|
||||||
const indexSource = buffer!.toString('utf-8');
|
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 { Tree } from '@angular-devkit/schematics';
|
||||||
import { createEmptyWorkspace } from '@nrwl/workspace/testing';
|
import { createEmptyWorkspace } from '@nrwl/workspace/testing';
|
||||||
import { readJsonInTree, updateJsonInTree } from '@nrwl/workspace';
|
import { NxJson, readJsonInTree, updateJsonInTree } from '@nrwl/workspace';
|
||||||
import { NxJson } from '@nrwl/workspace';
|
|
||||||
import { runSchematic } from '../../utils/testing';
|
import { runSchematic } from '../../utils/testing';
|
||||||
|
|
||||||
describe('lib', () => {
|
describe('lib', () => {
|
||||||
@ -398,7 +397,7 @@ describe('lib', () => {
|
|||||||
|
|
||||||
expect(workspaceJson.projects['my-lib'].architect.build).toMatchObject({
|
expect(workspaceJson.projects['my-lib'].architect.build).toMatchObject({
|
||||||
options: {
|
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(
|
const tree = await runSchematic(
|
||||||
'lib',
|
'lib',
|
||||||
{
|
{
|
||||||
@ -454,8 +453,8 @@ describe('lib', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const packageJson = readJsonInTree(tree, '/libs/my-lib/package.json');
|
const packageJson = readJsonInTree(tree, '/libs/my-lib/package.json');
|
||||||
|
|
||||||
expect(packageJson.name).toEqual('@proj/my-lib');
|
expect(packageJson.name).toEqual('@proj/my-lib');
|
||||||
|
expect(tree.exists('/libs/my-lib/.babelrc'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -47,6 +47,7 @@ import {
|
|||||||
} from '../../utils/versions';
|
} from '../../utils/versions';
|
||||||
import { Schema } from './schema';
|
import { Schema } from './schema';
|
||||||
import { libsDir } from '@nrwl/workspace/src/utils/ast-utils';
|
import { libsDir } from '@nrwl/workspace/src/utils/ast-utils';
|
||||||
|
import { initRootBabelConfig } from '@nrwl/web/src/utils/rules';
|
||||||
|
|
||||||
export interface NormalizedSchema extends Schema {
|
export interface NormalizedSchema extends Schema {
|
||||||
name: string;
|
name: string;
|
||||||
@ -99,6 +100,7 @@ export default function (schema: Schema): Rule {
|
|||||||
: noop(),
|
: noop(),
|
||||||
options.publishable ? updateLibPackageNpmScope(options) : noop(),
|
options.publishable ? updateLibPackageNpmScope(options) : noop(),
|
||||||
updateAppRoutes(options, context),
|
updateAppRoutes(options, context),
|
||||||
|
initRootBabelConfig(),
|
||||||
formatFiles(options),
|
formatFiles(options),
|
||||||
])(host, context);
|
])(host, context);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
import {
|
import {
|
||||||
|
babelPluginStyledComponentsVersion,
|
||||||
|
emotionBabelPresetCssPropVersion,
|
||||||
emotionCoreVersion,
|
emotionCoreVersion,
|
||||||
emotionStyledVersion,
|
emotionStyledVersion,
|
||||||
|
reactIsVersion,
|
||||||
styledComponentsVersion,
|
styledComponentsVersion,
|
||||||
|
typesReactIsVersion,
|
||||||
typesStyledComponentsVersion,
|
typesStyledComponentsVersion,
|
||||||
} from './versions';
|
} from './versions';
|
||||||
import { PackageDependencies } from './dependencies';
|
import { PackageDependencies } from './dependencies';
|
||||||
@ -11,10 +15,13 @@ export const CSS_IN_JS_DEPENDENCIES: {
|
|||||||
} = {
|
} = {
|
||||||
'styled-components': {
|
'styled-components': {
|
||||||
dependencies: {
|
dependencies: {
|
||||||
|
'react-is': reactIsVersion,
|
||||||
'styled-components': styledComponentsVersion,
|
'styled-components': styledComponentsVersion,
|
||||||
},
|
},
|
||||||
devDependencies: {
|
devDependencies: {
|
||||||
'@types/styled-components': typesStyledComponentsVersion,
|
'@types/styled-components': typesStyledComponentsVersion,
|
||||||
|
'@types/react-is': typesReactIsVersion,
|
||||||
|
'babel-plugin-styled-components': babelPluginStyledComponentsVersion,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'@emotion/styled': {
|
'@emotion/styled': {
|
||||||
@ -22,6 +29,8 @@ export const CSS_IN_JS_DEPENDENCIES: {
|
|||||||
'@emotion/styled': emotionStyledVersion,
|
'@emotion/styled': emotionStyledVersion,
|
||||||
'@emotion/core': emotionCoreVersion,
|
'@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 { Rule, Tree } from '@angular-devkit/schematics';
|
||||||
import { names } from '@nrwl/workspace/src/utils/name-utils';
|
import { names } from '@nrwl/workspace/src/utils/name-utils';
|
||||||
import { updateWorkspace } from '@nrwl/workspace/src/utils/workspace';
|
import { updateWorkspace } from '@nrwl/workspace/src/utils/workspace';
|
||||||
|
import { readJsonInTree } from '@nrwl/workspace';
|
||||||
|
|
||||||
const testRunner = new SchematicTestRunner(
|
const testRunner = new SchematicTestRunner(
|
||||||
'@nrwl/react',
|
'@nrwl/react',
|
||||||
@ -32,9 +33,48 @@ export function callRule(rule: Rule, tree: Tree) {
|
|||||||
return testRunner.callRule(rule, tree).toPromise();
|
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> {
|
export function createApp(tree: Tree, appName: string): Promise<Tree> {
|
||||||
const { fileName } = names(appName);
|
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(
|
return callRule(
|
||||||
updateWorkspace((workspace) => {
|
updateWorkspace((workspace) => {
|
||||||
workspace.projects.add({
|
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> {
|
export function createLib(tree: Tree, libName: string): Promise<Tree> {
|
||||||
const { fileName } = names(libName);
|
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(
|
return callRule(
|
||||||
updateWorkspace((workspace) => {
|
updateWorkspace((workspace) => {
|
||||||
|
|||||||
@ -1,26 +1,32 @@
|
|||||||
export const nxVersion = '*';
|
export const nxVersion = '*';
|
||||||
|
|
||||||
export const reactVersion = '16.12.0';
|
export const reactVersion = '16.13.1';
|
||||||
export const reactDomVersion = '16.12.0';
|
export const reactDomVersion = '16.13.1';
|
||||||
export const typesReactVersion = '16.9.17';
|
export const typesReactVersion = '16.9.35';
|
||||||
export const typesReactDomVersion = '16.9.4';
|
export const typesReactDomVersion = '16.9.8';
|
||||||
|
|
||||||
export const styledComponentsVersion = '5.0.1';
|
export const styledComponentsVersion = '5.1.0';
|
||||||
export const typesStyledComponentsVersion = '5.0.1';
|
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 emotionStyledVersion = '10.0.27';
|
||||||
export const emotionCoreVersion = '10.0.27';
|
export const emotionCoreVersion = '10.0.27';
|
||||||
|
export const emotionBabelPresetCssPropVersion = '10.0.27';
|
||||||
|
|
||||||
export const reactRouterDomVersion = '5.1.2';
|
export const reactRouterDomVersion = '5.2.0';
|
||||||
export const typesReactRouterDomVersion = '5.1.3';
|
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 reduxjsToolkitVersion = '1.3.6';
|
||||||
export const reactReduxVersion = '7.1.3';
|
export const reactReduxVersion = '7.2.0';
|
||||||
export const typesReactReduxVersion = '7.1.5';
|
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 eslintPluginJsxA11yVersion = '6.2.3';
|
||||||
export const eslintPluginReactVersion = '7.17.0';
|
export const eslintPluginReactVersion = '7.20.0';
|
||||||
export const eslintPluginReactHooksVersion = '2.3.0';
|
export const eslintPluginReactHooksVersion = '4.0.2';
|
||||||
|
|
||||||
|
export const babelPluginStyledComponentsVersion = '1.10.7';
|
||||||
|
|||||||
@ -32,7 +32,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nrwl/cypress": "*",
|
"@nrwl/cypress": "*",
|
||||||
"core-js": "^3.2.1",
|
"core-js": "^3.6.5",
|
||||||
"tree-kill": "1.2.2",
|
"tree-kill": "1.2.2",
|
||||||
"ts-loader": "5.3.1",
|
"ts-loader": "5.3.1",
|
||||||
"tsconfig-paths-webpack-plugin": "3.2.0",
|
"tsconfig-paths-webpack-plugin": "3.2.0",
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
export const nxVersion = '*';
|
export const nxVersion = '*';
|
||||||
export const storybookVersion = '5.3.9';
|
export const storybookVersion = '5.3.9';
|
||||||
export const babelCoreVersion = '7.8.3';
|
export const babelCoreVersion = '7.9.6';
|
||||||
export const babelLoaderVersion = '8.0.6';
|
export const babelLoaderVersion = '8.1.0';
|
||||||
export const babelPresetTypescriptVersion = '7.8.3';
|
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/build-webpack": "~0.901.0",
|
||||||
"@angular-devkit/core": "~9.1.0",
|
"@angular-devkit/core": "~9.1.0",
|
||||||
"@angular-devkit/schematics": "~9.1.0",
|
"@angular-devkit/schematics": "~9.1.0",
|
||||||
"@babel/core": "^7.8.4",
|
"@babel/core": "7.9.6",
|
||||||
"@babel/preset-env": "^7.8.4",
|
"@babel/preset-env": "7.9.6",
|
||||||
"@babel/preset-typescript": "^7.8.3",
|
"@babel/plugin-proposal-class-properties": "7.8.3",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
"@babel/plugin-proposal-decorators": "7.8.3",
|
||||||
"@babel/plugin-proposal-decorators": "^7.8.3",
|
"@babel/plugin-transform-regenerator": "7.8.7",
|
||||||
"@babel/plugin-transform-regenerator": "^7.8.3",
|
"@babel/preset-typescript": "7.9.0",
|
||||||
"@rollup/plugin-commonjs": "11.0.2",
|
"@rollup/plugin-commonjs": "11.0.2",
|
||||||
|
"@rollup/plugin-babel": "5.0.2",
|
||||||
"@rollup/plugin-image": "2.0.4",
|
"@rollup/plugin-image": "2.0.4",
|
||||||
"@rollup/plugin-node-resolve": "7.1.1",
|
"@rollup/plugin-node-resolve": "7.1.1",
|
||||||
"ajv": "6.10.2",
|
"ajv": "6.10.2",
|
||||||
"autoprefixer": "9.7.4",
|
"autoprefixer": "9.7.4",
|
||||||
"babel-loader": "8.0.6",
|
"babel-loader": "8.1.0",
|
||||||
"babel-plugin-const-enum": "0.0.5",
|
"babel-plugin-const-enum": "^1.0.1",
|
||||||
"babel-plugin-macros": "2.6.1",
|
"babel-plugin-macros": "^2.8.0",
|
||||||
"babel-plugin-transform-async-to-promises": "0.8.15",
|
"babel-plugin-transform-async-to-promises": "^0.8.15",
|
||||||
"browserslist": "4.8.7",
|
"browserslist": "4.8.7",
|
||||||
"cacache": "12.0.2",
|
"cacache": "12.0.2",
|
||||||
"caniuse-lite": "^1.0.30001030",
|
"caniuse-lite": "^1.0.30001030",
|
||||||
"circular-dependency-plugin": "5.2.0",
|
"circular-dependency-plugin": "5.2.0",
|
||||||
"clean-css": "4.2.1",
|
"clean-css": "4.2.1",
|
||||||
"copy-webpack-plugin": "5.1.1",
|
"copy-webpack-plugin": "5.1.1",
|
||||||
"core-js": "^3.2.1",
|
"core-js": "^3.6.5",
|
||||||
"css-loader": "3.4.2",
|
"css-loader": "3.4.2",
|
||||||
"file-loader": "4.2.0",
|
"file-loader": "4.2.0",
|
||||||
"find-cache-dir": "3.0.0",
|
"find-cache-dir": "3.0.0",
|
||||||
@ -84,13 +85,12 @@
|
|||||||
"rxjs": "^6.5.4",
|
"rxjs": "^6.5.4",
|
||||||
"regenerator-runtime": "0.13.3",
|
"regenerator-runtime": "0.13.3",
|
||||||
"rollup": "1.31.1",
|
"rollup": "1.31.1",
|
||||||
"rollup-plugin-babel": "4.3.3",
|
"rollup-plugin-copy": "^3.3.0",
|
||||||
"rollup-plugin-copy": "3.3.0",
|
"rollup-plugin-filesize": "^9.0.0",
|
||||||
"rollup-plugin-filesize": "6.2.1",
|
"rollup-plugin-local-resolve": "^1.0.7",
|
||||||
"rollup-plugin-local-resolve": "1.0.7",
|
"rollup-plugin-peer-deps-external": "^2.2.2",
|
||||||
"rollup-plugin-peer-deps-external": "2.2.2",
|
"rollup-plugin-postcss": "^3.1.1",
|
||||||
"rollup-plugin-postcss": "2.1.1",
|
"rollup-plugin-typescript2": "^0.27.1",
|
||||||
"rollup-plugin-typescript2": "0.26.0",
|
|
||||||
"sass": "1.22.9",
|
"sass": "1.22.9",
|
||||||
"sass-loader": "8.0.2",
|
"sass-loader": "8.0.2",
|
||||||
"semver": "6.3.0",
|
"semver": "6.3.0",
|
||||||
|
|||||||
@ -7,28 +7,22 @@ import {
|
|||||||
import { JsonObject } from '@angular-devkit/core';
|
import { JsonObject } from '@angular-devkit/core';
|
||||||
import { from, Observable, of } from 'rxjs';
|
import { from, Observable, of } from 'rxjs';
|
||||||
import { catchError, last, switchMap, tap } from 'rxjs/operators';
|
import { catchError, last, switchMap, tap } from 'rxjs/operators';
|
||||||
import { runRollup } from './run-rollup';
|
import { getBabelInputPlugin } from '@rollup/plugin-babel';
|
||||||
import { createBabelConfig as _createBabelConfig } from '../../utils/babel-config';
|
|
||||||
import * as autoprefixer from 'autoprefixer';
|
import * as autoprefixer from 'autoprefixer';
|
||||||
import * as rollup from 'rollup';
|
import * as rollup from 'rollup';
|
||||||
import * as babel from 'rollup-plugin-babel';
|
|
||||||
import * as peerDepsExternal from 'rollup-plugin-peer-deps-external';
|
import * as peerDepsExternal from 'rollup-plugin-peer-deps-external';
|
||||||
import * as postcss from 'rollup-plugin-postcss';
|
import * as postcss from 'rollup-plugin-postcss';
|
||||||
import * as filesize from 'rollup-plugin-filesize';
|
import * as filesize from 'rollup-plugin-filesize';
|
||||||
import * as localResolve from 'rollup-plugin-local-resolve';
|
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 { toClassName } from '@nrwl/workspace/src/utils/name-utils';
|
||||||
|
import { NodeJsSyncHost } from '@angular-devkit/core/node';
|
||||||
import { BuildResult } from '@angular-devkit/build-webpack';
|
import { BuildResult } from '@angular-devkit/build-webpack';
|
||||||
import {
|
import {
|
||||||
readJsonFile,
|
readJsonFile,
|
||||||
writeJsonFile,
|
writeJsonFile,
|
||||||
} from '@nrwl/workspace/src/utils/fileutils';
|
} from '@nrwl/workspace/src/utils/fileutils';
|
||||||
import { createProjectGraph } from '@nrwl/workspace/src/core/project-graph';
|
import { createProjectGraph } from '@nrwl/workspace/src/core/project-graph';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
calculateProjectDependencies,
|
calculateProjectDependencies,
|
||||||
checkDependentProjectsHaveBeenBuilt,
|
checkDependentProjectsHaveBeenBuilt,
|
||||||
@ -36,8 +30,15 @@ import {
|
|||||||
DependentBuildableProjectNode,
|
DependentBuildableProjectNode,
|
||||||
updateBuildableProjectPackageJsonDependencies,
|
updateBuildableProjectPackageJsonDependencies,
|
||||||
} from '@nrwl/workspace/src/utils/buildable-libs-utils';
|
} 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 { 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.
|
// These use require because the ES import isn't correct.
|
||||||
const resolve = require('@rollup/plugin-node-resolve');
|
const resolve = require('@rollup/plugin-node-resolve');
|
||||||
@ -88,7 +89,8 @@ export function run(
|
|||||||
options,
|
options,
|
||||||
dependencies,
|
dependencies,
|
||||||
context,
|
context,
|
||||||
packageJson
|
packageJson,
|
||||||
|
sourceRoot
|
||||||
);
|
);
|
||||||
|
|
||||||
if (options.watch) {
|
if (options.watch) {
|
||||||
@ -155,7 +157,8 @@ function createRollupOptions(
|
|||||||
options: NormalizedBundleBuilderOptions,
|
options: NormalizedBundleBuilderOptions,
|
||||||
dependencies: DependentBuildableProjectNode[],
|
dependencies: DependentBuildableProjectNode[],
|
||||||
context: BuilderContext,
|
context: BuilderContext,
|
||||||
packageJson: any
|
packageJson: any,
|
||||||
|
sourceRoot: string
|
||||||
): rollup.InputOptions {
|
): rollup.InputOptions {
|
||||||
const compilerOptionPaths = computeCompilerOptionsPaths(
|
const compilerOptionPaths = computeCompilerOptionsPaths(
|
||||||
options.tsConfig,
|
options.tsConfig,
|
||||||
@ -196,11 +199,20 @@ function createRollupOptions(
|
|||||||
preferBuiltins: true,
|
preferBuiltins: true,
|
||||||
extensions: fileExtensions,
|
extensions: fileExtensions,
|
||||||
}),
|
}),
|
||||||
babel({
|
getBabelInputPlugin({
|
||||||
...createBabelConfig(options, options.projectRoot),
|
// TODO(jack): Remove this in Nx 10
|
||||||
|
...legacyCreateBabelConfig(options, options.projectRoot),
|
||||||
|
|
||||||
|
cwd: join(context.workspaceRoot, sourceRoot),
|
||||||
|
rootMode: 'upward',
|
||||||
|
babelrc: true,
|
||||||
extensions: fileExtensions,
|
extensions: fileExtensions,
|
||||||
externalHelpers: false,
|
babelHelpers: 'bundled',
|
||||||
exclude: 'node_modules/**',
|
exclude: /node_modules/,
|
||||||
|
plugins: [
|
||||||
|
'babel-plugin-transform-async-to-promises',
|
||||||
|
['@babel/plugin-transform-regenerator', { async: false }],
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
commonjs(),
|
commonjs(),
|
||||||
filesize(),
|
filesize(),
|
||||||
@ -237,45 +249,46 @@ function createRollupOptions(
|
|||||||
: rollupConfig;
|
: rollupConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createBabelConfig(
|
function legacyCreateBabelConfig(
|
||||||
options: PackageBuilderOptions,
|
options: PackageBuilderOptions,
|
||||||
projectRoot: string
|
projectRoot: string
|
||||||
) {
|
) {
|
||||||
let babelConfig: any = _createBabelConfig(projectRoot, false, false);
|
|
||||||
if (options.babelConfig) {
|
if (options.babelConfig) {
|
||||||
|
let babelConfig: any = createBabelConfig(projectRoot, false, false);
|
||||||
babelConfig = require(options.babelConfig)(babelConfig, options);
|
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(
|
function upsert(
|
||||||
type: 'presets' | 'plugins',
|
type: 'presets' | 'plugins',
|
||||||
pluginOrPreset: string,
|
pluginOrPreset: string,
|
||||||
opts: null | JsonObject,
|
opts: null | JsonObject,
|
||||||
config: any
|
config: any
|
||||||
) {
|
|
||||||
if (
|
|
||||||
!config[type].some(
|
|
||||||
(p) =>
|
|
||||||
(Array.isArray(p) && p[0].indexOf(pluginOrPreset) !== -1) ||
|
|
||||||
p.indexOf(pluginOrPreset) !== -1
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
const fullPath = require.resolve(pluginOrPreset);
|
if (
|
||||||
config[type] = config[type].concat([opts ? [fullPath, opts] : fullPath]);
|
!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": {
|
"babelConfig": {
|
||||||
"type": "string",
|
"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": {
|
"umdName": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@ -48,6 +48,46 @@ describe('init', () => {
|
|||||||
},
|
},
|
||||||
tree
|
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 {
|
import {
|
||||||
addPackageWithInit,
|
addPackageWithInit,
|
||||||
formatFiles,
|
formatFiles,
|
||||||
@ -10,6 +10,7 @@ import {
|
|||||||
documentRegisterElementVersion,
|
documentRegisterElementVersion,
|
||||||
nxVersion,
|
nxVersion,
|
||||||
} from '../../utils/versions';
|
} from '../../utils/versions';
|
||||||
|
import { initRootBabelConfig } from '../../utils/rules';
|
||||||
|
|
||||||
function updateDependencies(): Rule {
|
function updateDependencies(): Rule {
|
||||||
return updateJsonInTree('package.json', (json) => {
|
return updateJsonInTree('package.json', (json) => {
|
||||||
@ -36,6 +37,7 @@ export default function (schema: Schema) {
|
|||||||
? addPackageWithInit('@nrwl/cypress')
|
? addPackageWithInit('@nrwl/cypress')
|
||||||
: noop(),
|
: noop(),
|
||||||
updateDependencies(),
|
updateDependencies(),
|
||||||
|
initRootBabelConfig(),
|
||||||
formatFiles(schema),
|
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(
|
export function createBabelConfig(
|
||||||
context: string,
|
context: string,
|
||||||
esm: boolean,
|
esm: boolean,
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { LicenseWebpackPlugin } from 'license-webpack-plugin';
|
|||||||
import TsConfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
|
import TsConfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
|
||||||
import { ProgressPlugin } from 'webpack';
|
import { ProgressPlugin } from 'webpack';
|
||||||
import { BuildBuilderOptions } from './types';
|
import { BuildBuilderOptions } from './types';
|
||||||
|
import { normalize } from '@angular-devkit/core';
|
||||||
import CircularDependencyPlugin = require('circular-dependency-plugin');
|
import CircularDependencyPlugin = require('circular-dependency-plugin');
|
||||||
import ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
import ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||||
|
|
||||||
@ -19,6 +20,7 @@ describe('getBaseWebpackPartial', () => {
|
|||||||
tsConfig: 'tsconfig.json',
|
tsConfig: 'tsconfig.json',
|
||||||
fileReplacements: [],
|
fileReplacements: [],
|
||||||
root: '/root',
|
root: '/root',
|
||||||
|
sourceRoot: normalize('/root/src'),
|
||||||
statsJson: false,
|
statsJson: false,
|
||||||
};
|
};
|
||||||
(<any>(
|
(<any>(
|
||||||
@ -164,12 +166,8 @@ describe('getBaseWebpackPartial', () => {
|
|||||||
|
|
||||||
expect(
|
expect(
|
||||||
(result.module.rules.find((rule) => rule.loader === 'babel-loader')
|
(result.module.rules.find((rule) => rule.loader === 'babel-loader')
|
||||||
.options as any).presets.find(
|
.options as any).envName
|
||||||
(p) => p[0].indexOf('@babel/preset-env') !== -1
|
).toMatch('modern');
|
||||||
)[1]
|
|
||||||
).toMatchObject({
|
|
||||||
targets: { esmodules: true },
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not override preset-env target for es5', () => {
|
it('should not override preset-env target for es5', () => {
|
||||||
@ -177,12 +175,8 @@ describe('getBaseWebpackPartial', () => {
|
|||||||
|
|
||||||
expect(
|
expect(
|
||||||
(result.module.rules.find((rule) => rule.loader === 'babel-loader')
|
(result.module.rules.find((rule) => rule.loader === 'babel-loader')
|
||||||
.options as any).presets.find(
|
.options as any).envName
|
||||||
(p) => p[0].indexOf('@babel/preset-env') !== -1
|
).toMatch('legacy');
|
||||||
)[1]
|
|
||||||
).toMatchObject({
|
|
||||||
targets: undefined,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import * as webpack from 'webpack';
|
import * as webpack from 'webpack';
|
||||||
import { Configuration, ProgressPlugin, Stats } 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 { LicenseWebpackPlugin } from 'license-webpack-plugin';
|
||||||
import * as CopyWebpackPlugin from 'copy-webpack-plugin';
|
import * as CopyWebpackPlugin from 'copy-webpack-plugin';
|
||||||
import * as TerserWebpackPlugin from 'terser-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 { AssetGlobPattern, BuildBuilderOptions } from './types';
|
||||||
import { getOutputHashFormat } from './hash-format';
|
import { getOutputHashFormat } from './hash-format';
|
||||||
import { createBabelConfig } from './babel-config';
|
|
||||||
import CircularDependencyPlugin = require('circular-dependency-plugin');
|
import CircularDependencyPlugin = require('circular-dependency-plugin');
|
||||||
import ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
import ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||||
|
|
||||||
@ -52,7 +51,10 @@ export function getBaseWebpackPartial(
|
|||||||
loader: `babel-loader`,
|
loader: `babel-loader`,
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
options: {
|
options: {
|
||||||
...createBabelConfig(dirname(options.main), esm, options.verbose),
|
rootMode: 'upward',
|
||||||
|
cwd: join(options.root, options.sourceRoot),
|
||||||
|
envName: esm ? 'modern' : 'legacy',
|
||||||
|
babelrc: true,
|
||||||
cacheDirectory: true,
|
cacheDirectory: true,
|
||||||
cacheCompression: false,
|
cacheCompression: false,
|
||||||
},
|
},
|
||||||
@ -153,7 +155,8 @@ export function createTerserPlugin(esm: boolean, sourceMap: boolean) {
|
|||||||
cache: true,
|
cache: true,
|
||||||
sourceMap,
|
sourceMap,
|
||||||
terserOptions: {
|
terserOptions: {
|
||||||
ecma: esm ? 6 : 5,
|
ecma: esm ? 8 : 5,
|
||||||
|
// Don't remove safari 10 workaround for ES modules
|
||||||
safari10: true,
|
safari10: true,
|
||||||
output: {
|
output: {
|
||||||
ascii_only: true,
|
ascii_only: true,
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
import { getDevServerConfig } from './devserver.config';
|
import { getDevServerConfig } from './devserver.config';
|
||||||
import { Logger } from '@angular-devkit/core/src/logger';
|
import { Logger } from '@angular-devkit/core/src/logger';
|
||||||
jest.mock('tsconfig-paths-webpack-plugin');
|
|
||||||
import TsConfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
|
import TsConfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import { WebBuildBuilderOptions } from '../builders/build/build.impl';
|
import { WebBuildBuilderOptions } from '../builders/build/build.impl';
|
||||||
import { WebDevServerOptions } from '../builders/dev-server/dev-server.impl';
|
import { WebDevServerOptions } from '../builders/dev-server/dev-server.impl';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
|
||||||
|
jest.mock('tsconfig-paths-webpack-plugin');
|
||||||
import ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
import ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||||
|
|
||||||
describe('getDevServerConfig', () => {
|
describe('getDevServerConfig', () => {
|
||||||
@ -18,6 +19,8 @@ describe('getDevServerConfig', () => {
|
|||||||
let sourceRoot: string;
|
let sourceRoot: string;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
root = join(__dirname, '../../../..');
|
||||||
|
sourceRoot = join(root, 'apps/app');
|
||||||
buildInput = {
|
buildInput = {
|
||||||
main: 'main.ts',
|
main: 'main.ts',
|
||||||
index: 'index.html',
|
index: 'index.html',
|
||||||
@ -39,9 +42,9 @@ describe('getDevServerConfig', () => {
|
|||||||
outputPath: 'dist',
|
outputPath: 'dist',
|
||||||
tsConfig: 'tsconfig.json',
|
tsConfig: 'tsconfig.json',
|
||||||
fileReplacements: [],
|
fileReplacements: [],
|
||||||
|
root,
|
||||||
|
sourceRoot,
|
||||||
};
|
};
|
||||||
root = join(__dirname, '../../../..');
|
|
||||||
sourceRoot = join(root, 'apps/app');
|
|
||||||
|
|
||||||
serveInput = {
|
serveInput = {
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
|
|||||||
@ -47,6 +47,8 @@ export function normalizeBuildOptions<T extends BuildBuilderOptions>(
|
|||||||
): T {
|
): T {
|
||||||
return {
|
return {
|
||||||
...options,
|
...options,
|
||||||
|
root,
|
||||||
|
sourceRoot,
|
||||||
main: resolve(root, options.main),
|
main: resolve(root, options.main),
|
||||||
outputPath: resolve(root, options.outputPath),
|
outputPath: resolve(root, options.outputPath),
|
||||||
tsConfig: resolve(root, options.tsConfig),
|
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 { FileReplacement } from './normalize';
|
||||||
import { JsonObject, Path } from '@angular-devkit/core';
|
import { JsonObject } from '@angular-devkit/core';
|
||||||
|
|
||||||
export interface OptimizationOptions {
|
export interface OptimizationOptions {
|
||||||
scripts: boolean;
|
scripts: boolean;
|
||||||
@ -37,7 +37,7 @@ export interface BuildBuilderOptions {
|
|||||||
webpackConfig?: string;
|
webpackConfig?: string;
|
||||||
|
|
||||||
root?: string;
|
root?: string;
|
||||||
sourceRoot?: Path;
|
sourceRoot?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Globals {
|
export interface Globals {
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { getWebConfig as getWebPartial } from './web.config';
|
import { getWebConfig as getWebPartial } from './web.config';
|
||||||
jest.mock('tsconfig-paths-webpack-plugin');
|
|
||||||
import TsConfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
|
import TsConfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
|
||||||
import { createConsoleLogger } from '@angular-devkit/core/node';
|
import { createConsoleLogger } from '@angular-devkit/core/node';
|
||||||
import { Logger } from '@angular-devkit/core/src/logger';
|
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 { WebBuildBuilderOptions } from '../builders/build/build.impl';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
|
||||||
|
jest.mock('tsconfig-paths-webpack-plugin');
|
||||||
|
|
||||||
describe('getWebConfig', () => {
|
describe('getWebConfig', () => {
|
||||||
let input: WebBuildBuilderOptions;
|
let input: WebBuildBuilderOptions;
|
||||||
let logger: Logger;
|
let logger: Logger;
|
||||||
@ -15,6 +16,8 @@ describe('getWebConfig', () => {
|
|||||||
let mockCompilerOptions: any;
|
let mockCompilerOptions: any;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
root = join(__dirname, '../../../..');
|
||||||
|
sourceRoot = join(root, 'apps/app');
|
||||||
input = {
|
input = {
|
||||||
main: 'main.ts',
|
main: 'main.ts',
|
||||||
index: 'index.html',
|
index: 'index.html',
|
||||||
@ -36,9 +39,9 @@ describe('getWebConfig', () => {
|
|||||||
outputPath: 'dist',
|
outputPath: 'dist',
|
||||||
tsConfig: 'tsconfig.json',
|
tsConfig: 'tsconfig.json',
|
||||||
fileReplacements: [],
|
fileReplacements: [],
|
||||||
|
root,
|
||||||
|
sourceRoot,
|
||||||
};
|
};
|
||||||
root = join(__dirname, '../../../..');
|
|
||||||
sourceRoot = join(root, 'apps/app');
|
|
||||||
logger = createConsoleLogger();
|
logger = createConsoleLogger();
|
||||||
|
|
||||||
mockCompilerOptions = {
|
mockCompilerOptions = {
|
||||||
|
|||||||
@ -6,16 +6,16 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
Rule,
|
|
||||||
Tree,
|
|
||||||
SchematicContext,
|
|
||||||
DirEntry,
|
|
||||||
noop,
|
|
||||||
chain,
|
|
||||||
Source,
|
|
||||||
mergeWith,
|
|
||||||
apply,
|
apply,
|
||||||
|
chain,
|
||||||
|
DirEntry,
|
||||||
forEach,
|
forEach,
|
||||||
|
mergeWith,
|
||||||
|
noop,
|
||||||
|
Rule,
|
||||||
|
SchematicContext,
|
||||||
|
Source,
|
||||||
|
Tree,
|
||||||
} from '@angular-devkit/schematics';
|
} from '@angular-devkit/schematics';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
import * as stripJsonComments from 'strip-json-comments';
|
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
|
* Method for utilizing the project graph in schematics
|
||||||
*/
|
*/
|
||||||
export function getProjectGraphFromHost(host: Tree): ProjectGraph {
|
export function getProjectGraphFromHost(host: Tree): ProjectGraph {
|
||||||
|
return onlyWorkspaceProjects(getFullProjectGraphFromHost(host));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFullProjectGraphFromHost(host: Tree): ProjectGraph {
|
||||||
const workspaceJson = readJsonInTree(host, getWorkspacePath(host));
|
const workspaceJson = readJsonInTree(host, getWorkspacePath(host));
|
||||||
const nxJson = readJsonInTree<NxJson>(host, '/nx.json');
|
const nxJson = readJsonInTree<NxJson>(host, '/nx.json');
|
||||||
|
|
||||||
@ -425,8 +429,12 @@ export function getProjectGraphFromHost(host: Tree): ProjectGraph {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return onlyWorkspaceProjects(
|
return createProjectGraph(
|
||||||
createProjectGraph(workspaceJson, nxJson, workspaceFiles, fileRead, false)
|
workspaceJson,
|
||||||
|
nxJson,
|
||||||
|
workspaceFiles,
|
||||||
|
fileRead,
|
||||||
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -59,8 +59,6 @@ function checkFiles(files: string[]) {
|
|||||||
r.package
|
r.package
|
||||||
)} has new version ${chalk.bold(r.latest)} (current: ${r.prev})`
|
)} 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
|
// 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';
|
||||||
import 'zone.js/dist/zone-testing';
|
import 'zone.js/dist/zone-testing';
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user