From b6ebc1c369a91e8a5cef2eea181b5b8b58a5da0b Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Mon, 9 Jan 2023 05:15:37 -0500 Subject: [PATCH] feat(webpack): remove support for legacy browsers (#14190) --- .../packages/react/generators/init.json | 2 +- .../packages/web/executors/webpack.json | 4 - .../packages/webpack/executors/webpack.json | 4 - e2e/nx-run/src/affected-graph.test.ts | 1 - e2e/web/src/file-server.test.ts | 7 +- e2e/web/src/web.test.ts | 17 - .../react/plugins/component-testing/index.ts | 1 - .../component-testing/webpack-fallback.ts | 2 +- packages/react/plugins/storybook/index.ts | 23 +- .../application/application.spec.ts | 15 - .../files/common/.browserslistrc__tmpl__ | 16 - .../files/common/src/polyfills.ts__tmpl__ | 7 - .../generators/application/lib/add-project.ts | 4 - packages/react/src/generators/init/init.ts | 2 - .../react/src/generators/init/schema.json | 2 +- packages/web/babel.ts | 1 - .../web/src/executors/webpack/schema.json | 4 - .../application/application.spec.ts | 1 - .../src/generators/application/application.ts | 4 - .../files/app/src/polyfills.ts__tmpl__ | 7 - packages/webpack/index.ts | 4 + packages/webpack/migrations.json | 6 + packages/webpack/package.json | 2 - .../dev-server/lib/get-dev-server-config.ts | 2 - .../webpack/lib/get-webpack-config.ts | 338 +------------ .../webpack/lib/normalize-options.ts | 6 +- .../webpack/src/executors/webpack/schema.d.ts | 1 - .../webpack/src/executors/webpack/schema.json | 4 - .../src/executors/webpack/webpack.impl.ts | 102 ++-- .../remove-es2015-polyfills-option.spec.ts | 67 +++ .../remove-es2015-polyfills-option.ts | 22 + .../generate-package-json-webpack-plugin.ts | 0 .../webpack/src/plugins/stats-json-plugin.ts | 10 + packages/webpack/src/utils/config.ts | 438 +--------------- .../webpack/src/utils/create-copy-plugin.ts | 24 + .../src/utils/get-client-environment.ts | 30 ++ .../src/utils/get-css-module-local-ident.ts | 31 ++ packages/webpack/src/utils/models.ts | 5 +- .../webpack/build-browser-features.spec.ts | 161 ------ .../utils/webpack/build-browser-features.ts | 78 --- .../src/utils/webpack/normalize-entry.ts | 20 +- .../src/utils/webpack/package-chunk-sort.ts | 6 +- .../src/utils/webpack/partials/browser.ts | 91 ---- .../src/utils/webpack/partials/common.ts | 249 --------- .../src/utils/webpack/partials/styles.ts | 219 -------- .../index-file/index-html-generator.ts | 11 +- .../plugins/index-html-webpack-plugin.ts | 7 +- .../utils/webpack/plugins/raw-css-loader.ts | 5 - .../src/utils/webpack/safari-nomodule.js | 23 - .../src/utils/webpack/write-index-html.ts | 20 +- packages/webpack/src/utils/with-nx.ts | 352 +++++++++++++ packages/webpack/src/utils/with-web.ts | 472 ++++++++++++++++++ 52 files changed, 1102 insertions(+), 1828 deletions(-) delete mode 100644 packages/react/src/generators/application/files/common/.browserslistrc__tmpl__ delete mode 100644 packages/react/src/generators/application/files/common/src/polyfills.ts__tmpl__ delete mode 100644 packages/web/src/generators/application/files/app/src/polyfills.ts__tmpl__ create mode 100644 packages/webpack/src/migrations/update-15-4-5/remove-es2015-polyfills-option.spec.ts create mode 100644 packages/webpack/src/migrations/update-15-4-5/remove-es2015-polyfills-option.ts rename packages/webpack/src/{utils => plugins}/generate-package-json-webpack-plugin.ts (100%) create mode 100644 packages/webpack/src/plugins/stats-json-plugin.ts create mode 100644 packages/webpack/src/utils/create-copy-plugin.ts create mode 100644 packages/webpack/src/utils/get-client-environment.ts create mode 100644 packages/webpack/src/utils/get-css-module-local-ident.ts delete mode 100644 packages/webpack/src/utils/webpack/build-browser-features.spec.ts delete mode 100644 packages/webpack/src/utils/webpack/build-browser-features.ts delete mode 100644 packages/webpack/src/utils/webpack/partials/browser.ts delete mode 100644 packages/webpack/src/utils/webpack/partials/common.ts delete mode 100644 packages/webpack/src/utils/webpack/partials/styles.ts delete mode 100644 packages/webpack/src/utils/webpack/plugins/raw-css-loader.ts delete mode 100644 packages/webpack/src/utils/webpack/safari-nomodule.js create mode 100644 packages/webpack/src/utils/with-nx.ts create mode 100644 packages/webpack/src/utils/with-web.ts diff --git a/docs/generated/packages/react/generators/init.json b/docs/generated/packages/react/generators/init.json index 1dc4ad03259eb1..5122a0829ac2be 100644 --- a/docs/generated/packages/react/generators/init.json +++ b/docs/generated/packages/react/generators/init.json @@ -37,7 +37,7 @@ "default": false }, "skipHelperLibs": { - "description": "Do not install helpers libs (tslib, core-js, regenerator-runtime).", + "description": "Do not install tslib.", "type": "boolean", "default": false, "hidden": true diff --git a/docs/generated/packages/web/executors/webpack.json b/docs/generated/packages/web/executors/webpack.json index d132d178304f87..b326f36f4bc419 100644 --- a/docs/generated/packages/web/executors/webpack.json +++ b/docs/generated/packages/web/executors/webpack.json @@ -300,10 +300,6 @@ "description": "Extract CSS into a `.css` file.", "default": true }, - "es2015Polyfills": { - "description": "Conditional polyfills loaded in browsers which do not support `ES2015`.", - "type": "string" - }, "subresourceIntegrity": { "type": "boolean", "description": "Enables the use of subresource integrity validation.", diff --git a/docs/generated/packages/webpack/executors/webpack.json b/docs/generated/packages/webpack/executors/webpack.json index b5205f93070602..978e1a70b5f4b2 100644 --- a/docs/generated/packages/webpack/executors/webpack.json +++ b/docs/generated/packages/webpack/executors/webpack.json @@ -307,10 +307,6 @@ "description": "Extract CSS into a `.css` file.", "default": true }, - "es2015Polyfills": { - "description": "Conditional polyfills loaded in browsers which do not support `ES2015`.", - "type": "string" - }, "subresourceIntegrity": { "type": "boolean", "description": "Enables the use of subresource integrity validation.", diff --git a/e2e/nx-run/src/affected-graph.test.ts b/e2e/nx-run/src/affected-graph.test.ts index b34b5be8cf3891..04afebbace74ee 100644 --- a/e2e/nx-run/src/affected-graph.test.ts +++ b/e2e/nx-run/src/affected-graph.test.ts @@ -597,7 +597,6 @@ describe('Nx Affected and Graph Tests', () => { expect(() => checkFilesExist('project-graph.html')).not.toThrow(); expect(() => checkFilesExist('static/styles.css')).not.toThrow(); expect(() => checkFilesExist('static/runtime.js')).not.toThrow(); - expect(() => checkFilesExist('static/polyfills.js')).not.toThrow(); expect(() => checkFilesExist('static/main.js')).not.toThrow(); expect(() => checkFilesExist('static/environment.js')).not.toThrow(); diff --git a/e2e/web/src/file-server.test.ts b/e2e/web/src/file-server.test.ts index 902f58463dd18b..369569cbbed699 100644 --- a/e2e/web/src/file-server.test.ts +++ b/e2e/web/src/file-server.test.ts @@ -26,10 +26,7 @@ describe('file-server', () => { const p = await runCommandUntil( `serve ${appName} --port=${port}`, (output) => { - return ( - output.indexOf('webpack compiled') > -1 && - output.indexOf(`localhost:${port}`) > -1 - ); + return output.indexOf(`localhost:${port}`) > -1; } ); @@ -39,5 +36,5 @@ describe('file-server', () => { } catch { // ignore } - }, 1000000); + }, 300_000); }); diff --git a/e2e/web/src/web.test.ts b/e2e/web/src/web.test.ts index 2f7e345e6dfdb6..c6857607704f61 100644 --- a/e2e/web/src/web.test.ts +++ b/e2e/web/src/web.test.ts @@ -112,23 +112,6 @@ describe('Web Components Applications', () => { checkFilesExist(`dist/libs/${libName}/_should_keep.txt`); }, 120000); - it('should do another build if differential loading is needed', async () => { - const appName = uniq('app'); - - runCLI( - `generate @nrwl/web:app ${appName} --bundler=webpack --no-interactive` - ); - - updateFile(`apps/${appName}/browserslist`, `IE 9-11`); - - runCLI(`build ${appName} --outputHashing=none`); - - checkFilesExist( - `dist/apps/${appName}/main.js`, - `dist/apps/${appName}/main.es5.js` - ); - }, 120000); - it('should emit decorator metadata when it is enabled in tsconfig', async () => { const appName = uniq('app'); runCLI( diff --git a/packages/react/plugins/component-testing/index.ts b/packages/react/plugins/component-testing/index.ts index 7c1a226effdf74..a463049bea9418 100644 --- a/packages/react/plugins/component-testing/index.ts +++ b/packages/react/plugins/component-testing/index.ts @@ -222,7 +222,6 @@ function buildTargetWebpack( const defaultWebpack = getWebpackConfig( context, options, - true, isScriptOptimizeOn, { root: ctProjectConfig.root, diff --git a/packages/react/plugins/component-testing/webpack-fallback.ts b/packages/react/plugins/component-testing/webpack-fallback.ts index 397314e16f08bf..a35a6933c86c5c 100644 --- a/packages/react/plugins/component-testing/webpack-fallback.ts +++ b/packages/react/plugins/component-testing/webpack-fallback.ts @@ -1,6 +1,6 @@ import { TsconfigPathsPlugin } from 'tsconfig-paths-webpack-plugin'; import { Configuration } from 'webpack'; -import { getCSSModuleLocalIdent } from '@nrwl/webpack/src/executors/webpack/lib/get-webpack-config'; +import { getCSSModuleLocalIdent } from '@nrwl/webpack'; export function buildBaseWebpackConfig({ tsConfigPath = 'tsconfig.cy.json', diff --git a/packages/react/plugins/storybook/index.ts b/packages/react/plugins/storybook/index.ts index e62db3befd13bc..bd0fc947461aba 100644 --- a/packages/react/plugins/storybook/index.ts +++ b/packages/react/plugins/storybook/index.ts @@ -1,23 +1,18 @@ import { - ExecutorContext, joinPathFragments, logger, - ProjectGraph, readJsonFile, - readNxJson, - TargetConfiguration, workspaceRoot, } from '@nrwl/devkit'; import { getBaseWebpackPartial } from '@nrwl/webpack/src/utils/config'; import { NormalizedWebpackExecutorOptions } from '@nrwl/webpack/src/executors/webpack/schema'; -import { getStylesPartial } from '@nrwl/webpack/src/executors/webpack/lib/get-webpack-config'; +// import { getStylesPartial } from '@nrwl/webpack/src/executors/webpack/lib/get-webpack-config'; import { checkAndCleanWithSemver } from '@nrwl/workspace/src/utilities/version-utils'; import { join } from 'path'; import { gte } from 'semver'; import { Configuration, DefinePlugin, WebpackPluginInstance } from 'webpack'; import * as mergeWebpack from 'webpack-merge'; import { mergePlugins } from './merge-plugins'; -import { readProjectsConfigurationFromProjectGraph } from 'nx/src/project-graph/project-graph'; const reactWebpackConfig = require('../webpack'); @@ -119,24 +114,12 @@ export const webpack = async ( target: 'web', }; - const esm = true; const isScriptOptimizeOn = storybookWebpackConfig.mode !== 'development'; const extractCss = storybookWebpackConfig.mode === 'production'; // ESM build for modern browsers. - const baseWebpackConfig = mergeWebpack.merge([ - getBaseWebpackPartial(builderOptions, { - esm, - isScriptOptimizeOn, - skipTypeCheck: true, - }), - getStylesPartial( - options.workspaceRoot, - options.configDir, - builderOptions, - extractCss - ), - ]); + let baseWebpackConfig: Configuration = {}; + baseWebpackConfig = getBaseWebpackPartial(builderOptions); // run it through the React customizations const finalConfig = reactWebpackConfig(baseWebpackConfig); diff --git a/packages/react/src/generators/application/application.spec.ts b/packages/react/src/generators/application/application.spec.ts index 12c42801e930b2..2c2cd18375d006 100644 --- a/packages/react/src/generators/application/application.spec.ts +++ b/packages/react/src/generators/application/application.spec.ts @@ -73,7 +73,6 @@ describe('app', () => { await applicationGenerator(appTree, schema); expect(appTree.exists('apps/my-app/.babelrc')).toBeTruthy(); - expect(appTree.exists('apps/my-app/.browserslistrc')).toBeTruthy(); expect(appTree.exists('apps/my-app/src/main.tsx')).toBeTruthy(); expect(appTree.exists('apps/my-app/src/app/app.tsx')).toBeTruthy(); expect(appTree.exists('apps/my-app/src/app/app.spec.tsx')).toBeTruthy(); @@ -312,7 +311,6 @@ describe('app', () => { main: 'apps/my-app/src/main.tsx', baseHref: '/', outputPath: 'dist/apps/my-app', - polyfills: 'apps/my-app/src/polyfills.ts', scripts: [], styles: ['apps/my-app/src/styles.css'], tsConfig: 'apps/my-app/tsconfig.app.json', @@ -810,19 +808,6 @@ describe('app', () => { ).toBeUndefined(); }); - it('should add required polyfills for core-js and regenerator', async () => { - await applicationGenerator(appTree, { - ...schema, - }); - - const polyfillsSource = appTree - .read('apps/my-app/src/polyfills.ts') - .toString(); - - expect(polyfillsSource).toContain('regenerator'); - expect(polyfillsSource).toContain('core-js'); - }); - describe('--skipWorkspaceJson', () => { it('should update workspace with defaults when --skipWorkspaceJson=false', async () => { await applicationGenerator(appTree, { diff --git a/packages/react/src/generators/application/files/common/.browserslistrc__tmpl__ b/packages/react/src/generators/application/files/common/.browserslistrc__tmpl__ deleted file mode 100644 index f1d12df4faa25a..00000000000000 --- a/packages/react/src/generators/application/files/common/.browserslistrc__tmpl__ +++ /dev/null @@ -1,16 +0,0 @@ -# This file is used by: -# 1. autoprefixer to adjust CSS to support the below specified browsers -# 2. babel preset-env to adjust included polyfills -# -# For additional information regarding the format and rule options, please see: -# https://github.com/browserslist/browserslist#queries -# -# If you need to support different browsers in production, you may tweak the list below. - -last 1 Chrome version -last 1 Firefox version -last 2 Edge major versions -last 2 Safari major version -last 2 iOS major versions -Firefox ESR -not IE 9-11 # For IE 9-11 support, remove 'not'. \ No newline at end of file diff --git a/packages/react/src/generators/application/files/common/src/polyfills.ts__tmpl__ b/packages/react/src/generators/application/files/common/src/polyfills.ts__tmpl__ deleted file mode 100644 index 2adf3d05b6fcf4..00000000000000 --- a/packages/react/src/generators/application/files/common/src/polyfills.ts__tmpl__ +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Polyfill stable language features. These imports will be optimized by `@babel/preset-env`. - * - * See: https://github.com/zloirock/core-js#babel - */ -import 'core-js/stable'; -import 'regenerator-runtime/runtime'; diff --git a/packages/react/src/generators/application/lib/add-project.ts b/packages/react/src/generators/application/lib/add-project.ts index 804900447a4d12..384e0a84e34ca9 100644 --- a/packages/react/src/generators/application/lib/add-project.ts +++ b/packages/react/src/generators/application/lib/add-project.ts @@ -57,10 +57,6 @@ function createBuildTarget(options: NormalizedSchema): TargetConfiguration { options.appProjectRoot, maybeJs(options, `src/main.tsx`) ), - polyfills: joinPathFragments( - options.appProjectRoot, - maybeJs(options, 'src/polyfills.ts') - ), tsConfig: joinPathFragments(options.appProjectRoot, 'tsconfig.app.json'), assets: [ joinPathFragments(options.appProjectRoot, 'src/favicon.ico'), diff --git a/packages/react/src/generators/init/init.ts b/packages/react/src/generators/init/init.ts index 171384eca47c3e..a50b41672a5818 100755 --- a/packages/react/src/generators/init/init.ts +++ b/packages/react/src/generators/init/init.ts @@ -52,8 +52,6 @@ function updateDependencies(host: Tree, schema: InitSchema) { }; if (!schema.skipHelperLibs) { - dependencies['core-js'] = '^3.6.5'; - dependencies['regenerator-runtime'] = '0.13.7'; dependencies['tslib'] = tsLibVersion; } diff --git a/packages/react/src/generators/init/schema.json b/packages/react/src/generators/init/schema.json index 1f907f6d259378..1c6800c0244a90 100644 --- a/packages/react/src/generators/init/schema.json +++ b/packages/react/src/generators/init/schema.json @@ -34,7 +34,7 @@ "default": false }, "skipHelperLibs": { - "description": "Do not install helpers libs (tslib, core-js, regenerator-runtime).", + "description": "Do not install tslib.", "type": "boolean", "default": false, "hidden": true diff --git a/packages/web/babel.ts b/packages/web/babel.ts index 602b1b10c11a9a..6ff992d615d0d2 100644 --- a/packages/web/babel.ts +++ b/packages/web/babel.ts @@ -43,7 +43,6 @@ module.exports = function (api: any, options: NxWebBabelPresetOptions = {}) { ? { targets: { node: 'current' }, loose: true } : { // Allow importing core-js in entrypoint and use browserlist to select polyfills. - // This is needed for differential loading as well. useBuiltIns: options.useBuiltIns ?? 'entry', corejs: 3, // Do not transform modules to CJS diff --git a/packages/web/src/executors/webpack/schema.json b/packages/web/src/executors/webpack/schema.json index 200624c469b832..51b7e81f9d6d2c 100644 --- a/packages/web/src/executors/webpack/schema.json +++ b/packages/web/src/executors/webpack/schema.json @@ -176,10 +176,6 @@ "description": "Extract CSS into a `.css` file.", "default": true }, - "es2015Polyfills": { - "description": "Conditional polyfills loaded in browsers which do not support `ES2015`.", - "type": "string" - }, "subresourceIntegrity": { "type": "boolean", "description": "Enables the use of subresource integrity validation.", diff --git a/packages/web/src/generators/application/application.spec.ts b/packages/web/src/generators/application/application.spec.ts index 23179043c18e0d..55c939ebebaab6 100644 --- a/packages/web/src/generators/application/application.spec.ts +++ b/packages/web/src/generators/application/application.spec.ts @@ -348,7 +348,6 @@ describe('app', () => { baseHref: '/', main: 'apps/my-app/src/main.ts', outputPath: 'dist/apps/my-app', - polyfills: 'apps/my-app/src/polyfills.ts', scripts: [], styles: ['apps/my-app/src/styles.css'], tsConfig: 'apps/my-app/tsconfig.app.json', diff --git a/packages/web/src/generators/application/application.ts b/packages/web/src/generators/application/application.ts index ba7e1899edec41..634f5bc130b542 100644 --- a/packages/web/src/generators/application/application.ts +++ b/packages/web/src/generators/application/application.ts @@ -91,10 +91,6 @@ async function setupBundler(tree: Tree, options: NormalizedSchema) { 'src/index.html' ); buildOptions.baseHref = '/'; - buildOptions.polyfills = joinPathFragments( - options.appProjectRoot, - 'src/polyfills.ts' - ); buildOptions.styles = [ joinPathFragments(options.appProjectRoot, `src/styles.${options.style}`), ]; diff --git a/packages/web/src/generators/application/files/app/src/polyfills.ts__tmpl__ b/packages/web/src/generators/application/files/app/src/polyfills.ts__tmpl__ deleted file mode 100644 index 2adf3d05b6fcf4..00000000000000 --- a/packages/web/src/generators/application/files/app/src/polyfills.ts__tmpl__ +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Polyfill stable language features. These imports will be optimized by `@babel/preset-env`. - * - * See: https://github.com/zloirock/core-js#babel - */ -import 'core-js/stable'; -import 'regenerator-runtime/runtime'; diff --git a/packages/webpack/index.ts b/packages/webpack/index.ts index 57e56c9b3afbc1..1cd12a35512ac2 100644 --- a/packages/webpack/index.ts +++ b/packages/webpack/index.ts @@ -1,3 +1,4 @@ +export * from './src/utils/create-copy-plugin'; export * from './src/utils/config'; export * from './src/generators/init/init'; export * from './src/generators/webpack-project/webpack-project'; @@ -11,3 +12,6 @@ export type { FileReplacement, } from './src/executors/webpack/schema'; export * from './src/executors/webpack/webpack.impl'; +export * from './src/utils/get-css-module-local-ident'; +export * from './src/utils/with-nx'; +export * from './src/utils/with-web'; diff --git a/packages/webpack/migrations.json b/packages/webpack/migrations.json index 75899c88e20553..f8d499c14cae9e 100644 --- a/packages/webpack/migrations.json +++ b/packages/webpack/migrations.json @@ -7,5 +7,11 @@ "factory": "./src/migrations/update-15-0-0/add-babel-inputs" } }, + "remove-es2015-polyfills-option": { + "cli": "nx", + "version": "15.4.5-beta.0", + "description": "Removes es2015Polyfills option since legacy browsers are no longer supported.", + "factory": "./src/migrations/update-15-4-5/remove-es2015-polyfills-option" + }, "packageJsonUpdates": {} } diff --git a/packages/webpack/package.json b/packages/webpack/package.json index cc257164bc849d..b327f4ad9b52b9 100644 --- a/packages/webpack/package.json +++ b/packages/webpack/package.json @@ -34,8 +34,6 @@ "@nrwl/workspace": "file:../workspace", "autoprefixer": "^10.4.9", "babel-loader": "^8.2.2", - "browserslist": "^4.21.4", - "caniuse-lite": "^1.0.30001394", "chalk": "4.1.0", "chokidar": "^3.5.1", "copy-webpack-plugin": "^10.2.4", diff --git a/packages/webpack/src/executors/dev-server/lib/get-dev-server-config.ts b/packages/webpack/src/executors/dev-server/lib/get-dev-server-config.ts index eae0b8b7a76056..cfbe56ca770aff 100644 --- a/packages/webpack/src/executors/dev-server/lib/get-dev-server-config.ts +++ b/packages/webpack/src/executors/dev-server/lib/get-dev-server-config.ts @@ -23,7 +23,6 @@ export function getDevServerConfig( const webpackConfig = getWebpackConfig( context, buildOptions, - true, typeof buildOptions.optimization === 'boolean' ? buildOptions.optimization : buildOptions.optimization?.scripts @@ -53,7 +52,6 @@ export function getDevServerConfig( deployUrl, sri: subresourceIntegrity, moduleEntrypoints: [], - noModuleEntrypoints: ['polyfills-es5'], }) ); diff --git a/packages/webpack/src/executors/webpack/lib/get-webpack-config.ts b/packages/webpack/src/executors/webpack/lib/get-webpack-config.ts index 10cdf2f3a50af5..9a2aef5eccb704 100644 --- a/packages/webpack/src/executors/webpack/lib/get-webpack-config.ts +++ b/packages/webpack/src/executors/webpack/lib/get-webpack-config.ts @@ -1,29 +1,11 @@ -import * as path from 'path'; -import { posix, resolve } from 'path'; -import { readTsConfig } from '@nrwl/workspace/src/utilities/typescript'; -import { ScriptTarget } from 'typescript'; -import { getHashDigest, interpolateName } from 'loader-utils'; import type { Configuration } from 'webpack'; +import { ExecutorContext } from '@nrwl/devkit'; import { NormalizedWebpackExecutorOptions } from '../schema'; - -// TODO(jack): These should be inlined in a single function so it is easier to understand -import { getBaseWebpackPartial } from '../../../utils/config'; -import { getBrowserConfig } from '../../../utils/webpack/partials/browser'; -import { getCommonConfig } from '../../../utils/webpack/partials/common'; -import { getStylesConfig } from '../../../utils/webpack/partials/styles'; -import { ExecutorContext } from '@nrwl/devkit'; -import MiniCssExtractPlugin = require('mini-css-extract-plugin'); +import { withNx } from '../../../utils/with-nx'; +import { withWeb } from '../../../utils/with-web'; import webpackMerge = require('webpack-merge'); -import postcssImports = require('postcss-import'); - -// PostCSS options depend on the webpack loader, but we need to set the `config` path as a string due to this check: -// https://github.com/webpack-contrib/postcss-loader/blob/0d342b1/src/utils.js#L36 -interface PostcssOptions { - (loader: any): any; - - config?: string; -} +import { composePlugins } from '@nrwl/webpack'; interface GetWebpackConfigOverrides { root: string; @@ -34,312 +16,12 @@ interface GetWebpackConfigOverrides { export function getWebpackConfig( context: ExecutorContext, options: NormalizedWebpackExecutorOptions, - esm?: boolean, - isScriptOptimizeOn?: boolean, - overrides?: GetWebpackConfigOverrides -): Configuration { - const tsConfig = readTsConfig(options.tsConfig); - const workspaceRoot = context.root; - - let sourceRoot: string; - let projectRoot: string; - if (overrides) { - projectRoot = overrides.root; - sourceRoot = overrides.sourceRoot; - } else { - const project = - context.projectsConfigurations.projects[context.projectName]; - projectRoot = project.root; - sourceRoot = project.sourceRoot; - } - - if (isScriptOptimizeOn) { - // Angular CLI uses an environment variable (NG_BUILD_DIFFERENTIAL_FULL) - // to determine whether to use the scriptTargetOverride - // or the tsConfig target - // We want to force the target if overridden - tsConfig.options.target = ScriptTarget.ES5; - } - const wco: any = { - root: workspaceRoot, - projectRoot: resolve(workspaceRoot, projectRoot), - sourceRoot: resolve(workspaceRoot, sourceRoot), - buildOptions: convertBuildOptions(options), - esm, - console, - tsConfig, - tsConfigPath: options.tsConfig, - }; - // TODO(jack): Replace merge behavior with an inlined config so it is easier to understand. - return webpackMerge.merge([ - _getBaseWebpackPartial( - context, - options, - esm, - isScriptOptimizeOn, - tsConfig.options.emitDecoratorMetadata, - overrides - ), - options.target === 'web' - ? getPolyfillsPartial( - options.polyfills, - options.es2015Polyfills, - esm, - isScriptOptimizeOn - ) - : {}, - options.target === 'web' - ? getStylesPartial( - wco.root, - wco.projectRoot, - wco.buildOptions, - options.extractCss, - options.postcssConfig - ) - : {}, - getCommonPartial(wco), - options.target === 'web' ? getBrowserConfig(wco) : {}, - ]); -} - -function _getBaseWebpackPartial( - context: ExecutorContext, - options: NormalizedWebpackExecutorOptions, - esm: boolean, - isScriptOptimizeOn: boolean, - emitDecoratorMetadata: boolean, + /** @deprecated Check options object instead */ + _isScriptOptimizeOn?: boolean, + // TODO(jack): The overrides object is needed for component testing (can we set it on context object?) overrides?: GetWebpackConfigOverrides -) { - let partial = getBaseWebpackPartial( - options, - { - esm, - isScriptOptimizeOn, - emitDecoratorMetadata, - configuration: overrides?.configuration ?? context.configurationName, - }, - context - ); - delete partial.resolve.mainFields; - return partial; -} - -function getCommonPartial(wco: any): Configuration { - const commonConfig: Configuration = getCommonConfig(wco); - delete commonConfig.entry; - delete commonConfig.resolve.modules; - delete commonConfig.resolve.extensions; - delete commonConfig.output.path; - delete commonConfig.module; - return commonConfig; -} - -export function getStylesPartial( - workspaceRoot: string, - projectRoot: string, - options: any, - extractCss: boolean, - postcssConfig?: string -): Configuration { - const includePaths: string[] = []; - - if (options?.stylePreprocessorOptions?.includePaths?.length > 0) { - options.stylePreprocessorOptions.includePaths.forEach( - (includePath: string) => - includePaths.push(path.resolve(workspaceRoot, includePath)) - ); - } - - const partial = getStylesConfig(workspaceRoot, options, includePaths); - const rules = partial.module.rules.map((rule) => { - if (!Array.isArray(rule.use)) { - return rule; - } - rule.use = rule.use.map((loaderConfig) => { - if ( - typeof loaderConfig === 'object' && - loaderConfig.loader === require.resolve('raw-loader') - ) { - return { - loader: require.resolve('style-loader'), - }; - } - return loaderConfig; - }); - return rule; - }); - - const loaderModulesOptions = { - modules: { - mode: 'local', - getLocalIdent: getCSSModuleLocalIdent, - }, - importLoaders: 1, - }; - const postcssOptions: PostcssOptions = () => ({ - plugins: [ - postcssImports({ - addModulesDirectories: includePaths, - resolve: (url: string) => (url.startsWith('~') ? url.slice(1) : url), - }), - ], - }); - // If a path to postcssConfig is passed in, set it for app and all libs, otherwise - // use automatic detection. - if (typeof postcssConfig === 'string') { - postcssOptions.config = path.join(workspaceRoot, postcssConfig); - } - - const commonLoaders = [ - { - loader: extractCss - ? MiniCssExtractPlugin.loader - : require.resolve('style-loader'), - }, - { - loader: require.resolve('css-loader'), - options: loaderModulesOptions, - }, - { - loader: require.resolve('postcss-loader'), - options: { - implementation: require('postcss'), - postcssOptions: postcssOptions, - }, - }, - ]; - - partial.module.rules = [ - { - test: /\.css$|\.scss$|\.sass$|\.less$|\.styl$/, - oneOf: [ - { - test: /\.module\.css$/, - use: commonLoaders, - }, - { - test: /\.module\.(scss|sass)$/, - use: [ - ...commonLoaders, - { - loader: require.resolve('sass-loader'), - options: { - implementation: require('sass'), - sassOptions: { - fiber: false, - precision: 8, - includePaths, - }, - }, - }, - ], - }, - { - test: /\.module\.less$/, - use: [ - ...commonLoaders, - { - loader: require.resolve('less-loader'), - options: { - lessOptions: { - paths: includePaths, - }, - }, - }, - ], - }, - { - test: /\.module\.styl$/, - use: [ - ...commonLoaders, - { - loader: require.resolve('stylus-loader'), - options: { - stylusOptions: { - include: includePaths, - }, - }, - }, - ], - }, - ...rules, - ], - }, - ]; - return partial; -} - -export function getPolyfillsPartial( - polyfills: string, - es2015Polyfills: string, - esm: boolean, - isScriptOptimizeOn: boolean ): Configuration { - const config = { - entry: {} as { [key: string]: string[] }, - }; - - if (polyfills && esm && isScriptOptimizeOn) { - // Safari 10.1 supports