From baab09eabd89dd554164307d5c4c0362bfe41311 Mon Sep 17 00:00:00 2001 From: John Reilly Date: Tue, 12 Sep 2017 12:34:55 +0100 Subject: [PATCH 1/3] Add support for fork-ts-checker-webpack-plugin --- .../config/webpack.config.dev.js | 28 +++++++++++++------ .../config/webpack.config.prod.js | 28 +++++++++++++------ packages/react-scripts/package.json | 4 ++- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/packages/react-scripts/config/webpack.config.dev.js b/packages/react-scripts/config/webpack.config.dev.js index 2934aeae6..ff4a02901 100644 --- a/packages/react-scripts/config/webpack.config.dev.js +++ b/packages/react-scripts/config/webpack.config.dev.js @@ -18,6 +18,7 @@ const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin'); const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin'); const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin'); const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); +const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); const getClientEnvironment = require('./env'); const paths = require('./paths'); @@ -136,14 +137,6 @@ module.exports = { // We are waiting for https://github.com/facebookincubator/create-react-app/issues/2176. // { parser: { requireEnsure: false } }, - // First, run the linter. - // It's important to do this before Babel processes the JS. - { - test: /\.(ts|tsx)$/, - loader: require.resolve('tslint-loader'), - enforce: 'pre', - include: paths.appSrc, - }, { test: /\.js$/, loader: require.resolve('source-map-loader'), @@ -197,7 +190,22 @@ module.exports = { { test: /\.(ts|tsx)$/, include: paths.appSrc, - loader: require.resolve('ts-loader'), + use: [ + { loader: 'cache-loader' }, + { + loader: 'thread-loader', + options: { + // there should be 1 cpu for the fork-ts-checker-webpack-plugin + workers: require('os').cpus().length - 1, + }, + }, + { + loader: 'ts-loader', + options: { + happyPackMode: true // IMPORTANT! use happyPackMode mode to speed-up compilation and reduce errors reported to webpack + } + } + ], }, // "postcss" loader applies autoprefixer to our CSS. // "css" loader resolves paths in CSS and adds assets as dependencies. @@ -273,6 +281,8 @@ module.exports = { // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack // You can remove this if you don't use Moment.js: new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), + // Perform type checking and linting in a separate process to speed up compilation + new ForkTsCheckerWebpackPlugin({ checkSyntacticErrors: true, async: false, tslint: true }), ], // Some libraries import Node modules but don't use them in the browser. // Tell Webpack to provide empty mocks for them so importing them works. diff --git a/packages/react-scripts/config/webpack.config.prod.js b/packages/react-scripts/config/webpack.config.prod.js index 8519c6603..67443dce2 100644 --- a/packages/react-scripts/config/webpack.config.prod.js +++ b/packages/react-scripts/config/webpack.config.prod.js @@ -19,6 +19,7 @@ const ManifestPlugin = require('webpack-manifest-plugin'); const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin'); const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin'); const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); +const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); const paths = require('./paths'); const getClientEnvironment = require('./env'); @@ -136,14 +137,6 @@ module.exports = { // We are waiting for https://github.com/facebookincubator/create-react-app/issues/2176. // { parser: { requireEnsure: false } }, - // First, run the linter. - // It's important to do this before Typescript runs. - { - test: /\.(ts|tsx)$/, - loader: require.resolve('tslint-loader'), - enforce: 'pre', - include: paths.appSrc, - }, { test: /\.js$/, loader: require.resolve('source-map-loader'), @@ -189,7 +182,22 @@ module.exports = { { test: /\.(ts|tsx)$/, include: paths.appSrc, - loader: require.resolve('ts-loader') + use: [ + { loader: 'cache-loader' }, + { + loader: 'thread-loader', + options: { + // there should be 1 cpu for the fork-ts-checker-webpack-plugin + workers: require('os').cpus().length - 1, + }, + }, + { + loader: 'ts-loader', + options: { + happyPackMode: true // IMPORTANT! use happyPackMode mode to speed-up compilation and reduce errors reported to webpack + } + } + ], }, // The notation here is somewhat confusing. // "postcss" loader applies autoprefixer to our CSS. @@ -342,6 +350,8 @@ module.exports = { // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack // You can remove this if you don't use Moment.js: new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), + // Perform type checking and linting in a separate process to speed up compilation + new ForkTsCheckerWebpackPlugin({ checkSyntacticErrors: true, async: false, tslint: true }), ], // Some libraries import Node modules but don't use them in the browser. // Tell Webpack to provide empty mocks for them so importing them works. diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 39b2f69fa..86f78818f 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -24,6 +24,7 @@ "dependencies": { "autoprefixer": "7.1.1", "app-root-path": "^2.0.1", + "cache-loader": "^1.0.3", "case-sensitive-paths-webpack-plugin": "2.1.1", "chalk": "1.1.3", "cli-highlight": "1.1.4", @@ -31,6 +32,7 @@ "dotenv": "4.0.0", "extract-text-webpack-plugin": "2.1.2", "file-loader": "0.11.2", + "fork-ts-checker-webpack-plugin": "^0.2.8", "fs-extra": "3.0.1", "html-webpack-plugin": "2.28.0", "jest": "20.0.3", @@ -41,10 +43,10 @@ "react-dev-utils": "^3.0.1", "react-error-overlay": "^1.0.8", "style-loader": "0.18.2", + "thread-loader": "^1.1.1", "ts-jest": "^20.0.7", "ts-loader": "^2.2.1", "tslint": "^5.2.0", - "tslint-loader": "^3.5.3", "tslint-react": "^3.0.0", "typescript": "~2.4.0", "source-map-loader": "^0.2.1", From 5e989d36aa58f30df1b9c497d5bb7c202d22bdee Mon Sep 17 00:00:00 2001 From: John Reilly Date: Tue, 19 Sep 2017 06:32:58 +0100 Subject: [PATCH 2/3] remove thread-loader and cache loader and apply @DorianGrey suggestions --- packages/react-scripts/config/paths.js | 1 + .../config/webpack.config.dev.js | 24 +++++++++---------- .../config/webpack.config.prod.js | 23 ++++++++---------- packages/react-scripts/package.json | 2 -- 4 files changed, 22 insertions(+), 28 deletions(-) diff --git a/packages/react-scripts/config/paths.js b/packages/react-scripts/config/paths.js index e860d9b04..0d85ff15b 100644 --- a/packages/react-scripts/config/paths.js +++ b/packages/react-scripts/config/paths.js @@ -114,6 +114,7 @@ if ( testsSetup: resolveOwn('template/src/setupTests.ts'), appNodeModules: resolveOwn('node_modules'), appTsConfig: resolveOwn('template/tsconfig.json'), + appTsLint: resolveOwn('template/tslint.json'), appTsTestConfig: resolveOwn('template/tsconfig.test.json'), publicUrl: getPublicUrl(resolveOwn('package.json')), servedPath: getServedPath(resolveOwn('package.json')), diff --git a/packages/react-scripts/config/webpack.config.dev.js b/packages/react-scripts/config/webpack.config.dev.js index ff4a02901..06b29918e 100644 --- a/packages/react-scripts/config/webpack.config.dev.js +++ b/packages/react-scripts/config/webpack.config.dev.js @@ -191,20 +191,13 @@ module.exports = { test: /\.(ts|tsx)$/, include: paths.appSrc, use: [ - { loader: 'cache-loader' }, { - loader: 'thread-loader', - options: { - // there should be 1 cpu for the fork-ts-checker-webpack-plugin - workers: require('os').cpus().length - 1, - }, + loader: 'ts-loader', + options: { + // disable type checker - we will use it in fork plugin + transpileOnly: true, + }, }, - { - loader: 'ts-loader', - options: { - happyPackMode: true // IMPORTANT! use happyPackMode mode to speed-up compilation and reduce errors reported to webpack - } - } ], }, // "postcss" loader applies autoprefixer to our CSS. @@ -282,7 +275,12 @@ module.exports = { // You can remove this if you don't use Moment.js: new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), // Perform type checking and linting in a separate process to speed up compilation - new ForkTsCheckerWebpackPlugin({ checkSyntacticErrors: true, async: false, tslint: true }), + new ForkTsCheckerWebpackPlugin({ + async: false, + watch: paths.appSrc, + tsconfig: paths.appTsConfig, + tslint: paths.appTsLint, + }), ], // Some libraries import Node modules but don't use them in the browser. // Tell Webpack to provide empty mocks for them so importing them works. diff --git a/packages/react-scripts/config/webpack.config.prod.js b/packages/react-scripts/config/webpack.config.prod.js index 67443dce2..75817e398 100644 --- a/packages/react-scripts/config/webpack.config.prod.js +++ b/packages/react-scripts/config/webpack.config.prod.js @@ -183,20 +183,13 @@ module.exports = { test: /\.(ts|tsx)$/, include: paths.appSrc, use: [ - { loader: 'cache-loader' }, { - loader: 'thread-loader', - options: { - // there should be 1 cpu for the fork-ts-checker-webpack-plugin - workers: require('os').cpus().length - 1, - }, + loader: 'ts-loader', + options: { + // disable type checker - we will use it in fork plugin + transpileOnly: true, + }, }, - { - loader: 'ts-loader', - options: { - happyPackMode: true // IMPORTANT! use happyPackMode mode to speed-up compilation and reduce errors reported to webpack - } - } ], }, // The notation here is somewhat confusing. @@ -351,7 +344,11 @@ module.exports = { // You can remove this if you don't use Moment.js: new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), // Perform type checking and linting in a separate process to speed up compilation - new ForkTsCheckerWebpackPlugin({ checkSyntacticErrors: true, async: false, tslint: true }), + new ForkTsCheckerWebpackPlugin({ + async: false, + tsconfig: paths.appTsConfig, + tslint: paths.appTsLint, + }), ], // Some libraries import Node modules but don't use them in the browser. // Tell Webpack to provide empty mocks for them so importing them works. diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 86f78818f..48804800f 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -24,7 +24,6 @@ "dependencies": { "autoprefixer": "7.1.1", "app-root-path": "^2.0.1", - "cache-loader": "^1.0.3", "case-sensitive-paths-webpack-plugin": "2.1.1", "chalk": "1.1.3", "cli-highlight": "1.1.4", @@ -43,7 +42,6 @@ "react-dev-utils": "^3.0.1", "react-error-overlay": "^1.0.8", "style-loader": "0.18.2", - "thread-loader": "^1.1.1", "ts-jest": "^20.0.7", "ts-loader": "^2.2.1", "tslint": "^5.2.0", From c6ac48b923610773829db6fbc8da0465cc50e9b9 Mon Sep 17 00:00:00 2001 From: John Reilly Date: Tue, 19 Sep 2017 07:18:33 +0100 Subject: [PATCH 3/3] Fixup merge --- .../config/webpack.config.dev.js | 164 +++++++-------- .../config/webpack.config.prod.js | 194 +++++++++--------- 2 files changed, 174 insertions(+), 184 deletions(-) diff --git a/packages/react-scripts/config/webpack.config.dev.js b/packages/react-scripts/config/webpack.config.dev.js index 06b29918e..6c619f4f4 100644 --- a/packages/react-scripts/config/webpack.config.dev.js +++ b/packages/react-scripts/config/webpack.config.dev.js @@ -43,6 +43,8 @@ module.exports = { // This means they will be the "root" imports that are included in JS bundle. // The first two entry points enable "hot" CSS and auto-refreshes for JS. entry: [ + // We ship a few polyfills by default: + require.resolve('./polyfills'), // Include an alternative client for WebpackDevServer. A client's job is to // connect to WebpackDevServer by a socket and get notified about changes. // When you save a file, the client will either apply hot updates (in case @@ -54,10 +56,6 @@ module.exports = { // require.resolve('webpack-dev-server/client') + '?/', // require.resolve('webpack/hot/dev-server'), require.resolve('react-dev-utils/webpackHotDevClient'), - // We ship a few polyfills by default: - require.resolve('./polyfills'), - // Errors should be considered fatal in development - require.resolve('react-error-overlay'), // Finally, this is your app's code: paths.appIndexJs, // We include the app code last so that if there is a runtime error during @@ -127,7 +125,7 @@ module.exports = { // To fix this, we prevent you from importing files out of src/ -- if you'd like to, // please link the files into your node_modules/ and let module-resolution kick in. // Make sure your source files are compiled, as they will not be processed in any way. - new ModuleScopePlugin(paths.appSrc), + new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]), ], }, module: { @@ -143,102 +141,93 @@ module.exports = { enforce: 'pre', include: paths.appSrc, }, - // ** ADDING/UPDATING LOADERS ** - // The "file" loader handles all assets unless explicitly excluded. - // The `exclude` list *must* be updated with every change to loader extensions. - // When adding a new loader, you must add its `test` - // as a new entry in the `exclude` list for "file" loader. - - // "file" loader makes sure those assets get served by WebpackDevServer. - // When you `import` an asset, you get its (virtual) filename. - // In production, they would get copied to the `build` folder. - { - exclude: [ - /\.html$/, - // We have to write /\.(js|jsx)(\?.*)?$/ rather than just /\.(js|jsx)$/ - // because you might change the hot reloading server from the custom one - // to Webpack's built-in webpack-dev-server/client?/, which would not - // get properly excluded by /\.(js|jsx)$/ because of the query string. - // Webpack 2 fixes this, but for now we include this hack. - // https://github.com/facebookincubator/create-react-app/issues/1713 - /\.(js|jsx)(\?.*)?$/, - /\.(ts|tsx)(\?.*)?$/, - /\.css$/, - /\.json$/, - /\.bmp$/, - /\.gif$/, - /\.jpe?g$/, - /\.png$/, - ], - loader: require.resolve('file-loader'), - options: { - name: 'static/media/[name].[hash:8].[ext]', - }, - }, - // "url" loader works like "file" loader except that it embeds assets - // smaller than specified limit in bytes as data URLs to avoid requests. - // A missing `test` is equivalent to a match. - { - test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], - loader: require.resolve('url-loader'), - options: { - limit: 10000, - name: 'static/media/[name].[hash:8].[ext]', - }, - }, - // Compile .tsx? { - test: /\.(ts|tsx)$/, - include: paths.appSrc, - use: [ + // "oneOf" will traverse all following loaders until one will + // match the requirements. When no loader matches it will fall + // back to the "file" loader at the end of the loader list. + oneOf: [ + // "url" loader works like "file" loader except that it embeds assets + // smaller than specified limit in bytes as data URLs to avoid requests. + // A missing `test` is equivalent to a match. { - loader: 'ts-loader', + test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], + loader: require.resolve('url-loader'), options: { - // disable type checker - we will use it in fork plugin - transpileOnly: true, + limit: 10000, + name: 'static/media/[name].[hash:8].[ext]', }, }, - ], - }, - // "postcss" loader applies autoprefixer to our CSS. - // "css" loader resolves paths in CSS and adds assets as dependencies. - // "style" loader turns CSS into JS modules that inject