diff --git a/package.json b/package.json index 1084992025b..07773fba88f 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,6 @@ { "private": true, - "workspaces": [ - "packages/*" - ], + "workspaces": ["packages/*"], "scripts": { "build": "cd packages/react-scripts && node bin/react-scripts.js build", "changelog": "lerna-changelog", @@ -13,10 +11,12 @@ "publish": "tasks/publish.sh", "start": "cd packages/react-scripts && node bin/react-scripts.js start", "screencast": "node ./tasks/screencast.js", - "screencast:error": "svg-term --cast jyu19xGl88FQ3poMY8Hbmfw8y --out screencast-error.svg --window --at 12000 --no-cursor", - "test": "cd packages/react-scripts && node bin/react-scripts.js test --env=jsdom", - "format": "prettier --trailing-comma es5 --single-quote --write 'packages/*/*.js' 'packages/*/!(node_modules)/**/*.js'", - "precommit": "lint-staged" + "screencast:error": + "svg-term --cast jyu19xGl88FQ3poMY8Hbmfw8y --out screencast-error.svg --window --at 12000 --no-cursor", + "test": + "cd packages/react-scripts && node bin/react-scripts.js test --env=jsdom", + "format": + "prettier --trailing-comma es5 --single-quote --write 'packages/*/*.js' 'packages/*/!(node_modules)/**/*.js'" }, "devDependencies": { "eslint": "4.15.0", @@ -30,14 +30,5 @@ "prettier": "1.6.1", "svg-term-cli": "^2.0.3", "tempy": "^0.2.1" - }, - "lint-staged": { - "*.js": [ - "prettier --trailing-comma es5 --single-quote --write", - "git add" - ], - "yarn.lock": [ - "git rm --cached" - ] } } diff --git a/packages/confusing-browser-globals/package.json b/packages/confusing-browser-globals/package.json index 874bec0a52b..f9212a62388 100644 --- a/packages/confusing-browser-globals/package.json +++ b/packages/confusing-browser-globals/package.json @@ -16,6 +16,6 @@ "index.js" ], "devDependencies": { - "jest": "22.4.1" + "jest": "^23.6.0" } } diff --git a/packages/react-dev-utils/package.json b/packages/react-dev-utils/package.json index 48197f822c3..799ae7965a4 100644 --- a/packages/react-dev-utils/package.json +++ b/packages/react-dev-utils/package.json @@ -62,7 +62,7 @@ "text-table": "0.2.0" }, "devDependencies": { - "jest": "22.4.1" + "jest": "^23.6.0" }, "scripts": { "test": "jest" diff --git a/packages/react-error-overlay/package.json b/packages/react-error-overlay/package.json index f6b45a1d5e8..80fb0c416fe 100644 --- a/packages/react-error-overlay/package.json +++ b/packages/react-error-overlay/package.json @@ -50,7 +50,7 @@ "eslint-plugin-react": "7.7.0", "flow-bin": "^0.63.1", "html-entities": "1.2.1", - "jest": "22.4.1", + "jest": "^23.6.0", "jest-fetch-mock": "1.2.1", "object-assign": "4.1.1", "promise": "8.0.1", diff --git a/packages/react-scripts/README.md b/packages/react-scripts/README.md index f2a2994f00c..8a1ce5035d5 100644 --- a/packages/react-scripts/README.md +++ b/packages/react-scripts/README.md @@ -1,6 +1,14 @@ -# react-scripts +# byted-react-scripts -This package includes scripts and configuration used by [Create React App](https://github.com/facebook/create-react-app).
+__usage:__ + +```sh +create-react-app --scripts-version=byted-react-scripts dirname +``` + + + +This package includes scripts and configuration forked from [Create React App](https://github.com/facebook/create-react-app).
Please refer to its documentation: * [Getting Started](https://github.com/facebook/create-react-app/blob/master/README.md#getting-started) – How to create a new app. diff --git a/packages/react-scripts/bin/react-scripts.js b/packages/react-scripts/bin/react-scripts.js index 9ad5fccff88..7030eec0214 100755 --- a/packages/react-scripts/bin/react-scripts.js +++ b/packages/react-scripts/bin/react-scripts.js @@ -57,9 +57,6 @@ switch (script) { } default: console.log('Unknown script "' + script + '".'); - console.log('Perhaps you need to update react-scripts?'); - console.log( - 'See: https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#updating-to-new-releases' - ); + console.log('Perhaps you need to update byted-react-scripts?'); break; } diff --git a/packages/react-scripts/config/env.js b/packages/react-scripts/config/env.js index 7565cecd001..1e9316d0ca8 100644 --- a/packages/react-scripts/config/env.js +++ b/packages/react-scripts/config/env.js @@ -30,7 +30,7 @@ var dotenvFiles = [ // since normally you expect tests to produce the same // results for everyone NODE_ENV !== 'test' && `${paths.dotenv}.local`, - paths.dotenv, + paths.dotenv ].filter(Boolean); // Load environment variables from .env* files. Suppress warnings using silent @@ -42,7 +42,7 @@ dotenvFiles.forEach(dotenvFile => { if (fs.existsSync(dotenvFile)) { require('dotenv-expand')( require('dotenv').config({ - path: dotenvFile, + path: dotenvFile }) ); } @@ -84,7 +84,7 @@ function getClientEnvironment(publicUrl) { // For example, . // This should only be used as an escape hatch. Normally you would put // images into the `src` and `import` them in code to get their paths. - PUBLIC_URL: publicUrl, + PUBLIC_URL: publicUrl } ); // Stringify all values so we can feed into Webpack DefinePlugin @@ -92,7 +92,7 @@ function getClientEnvironment(publicUrl) { 'process.env': Object.keys(raw).reduce((env, key) => { env[key] = JSON.stringify(raw[key]); return env; - }, {}), + }, {}) }; return { raw, stringified }; diff --git a/packages/react-scripts/config/jest/typescriptTransform.js b/packages/react-scripts/config/jest/typescriptTransform.js new file mode 100644 index 00000000000..9b138ac8ecb --- /dev/null +++ b/packages/react-scripts/config/jest/typescriptTransform.js @@ -0,0 +1,7 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +'use strict'; + +const tsJestPreprocessor = require('ts-jest/preprocessor'); + +module.exports = tsJestPreprocessor; diff --git a/packages/react-scripts/config/paths.js b/packages/react-scripts/config/paths.js index d7f55b6f638..d1179209193 100644 --- a/packages/react-scripts/config/paths.js +++ b/packages/react-scripts/config/paths.js @@ -13,6 +13,9 @@ const fs = require('fs'); const url = require('url'); const findMonorepo = require('react-dev-utils/workspaceUtils').findMonorepo; +const LANG = process.env.DEV_LANG || 'javascript'; +const EXT = LANG === 'javascript' ? '.js' : '.tsx'; + // Make sure any symlinks in the project folder are resolved: // https://github.com/facebook/create-react-app/issues/637 const appDirectory = fs.realpathSync(process.cwd()); @@ -54,12 +57,15 @@ module.exports = { appBuild: resolveApp('build'), appPublic: resolveApp('public'), appHtml: resolveApp('public/index.html'), - appIndexJs: resolveApp('src/index.js'), + appIndexJs: resolveApp(`src/index${EXT}`), appPackageJson: resolveApp('package.json'), appSrc: resolveApp('src'), - testsSetup: resolveApp('src/setupTests.js'), + testsSetup: resolveApp(`src/setupTests${EXT}`), appNodeModules: resolveApp('node_modules'), publicUrl: getPublicUrl(resolveApp('package.json')), + appTsConfig: resolveApp('tsconfig.json'), + appTsProdConfig: resolveApp('tsconfig.prod.json'), + appTsLint: resolveApp('tslint.json'), servedPath: getServedPath(resolveApp('package.json')), }; @@ -75,12 +81,16 @@ module.exports = { appBuild: resolveApp('build'), appPublic: resolveApp('public'), appHtml: resolveApp('public/index.html'), - appIndexJs: resolveApp('src/index.js'), + appIndexJs: resolveApp(`src/index${EXT}`), appPackageJson: resolveApp('package.json'), appSrc: resolveApp('src'), - testsSetup: resolveApp('src/setupTests.js'), + testsSetup: resolveApp(`src/setupTests${EXT}`), appNodeModules: resolveApp('node_modules'), publicUrl: getPublicUrl(resolveApp('package.json')), + appTsConfig: resolveApp('tsconfig.json'), + appTsTestConfig: resolveApp('tsconfig.test.json'), + appTsProdConfig: resolveApp('tsconfig.prod.json'), + appTsLint: resolveApp('tslint.json'), servedPath: getServedPath(resolveApp('package.json')), // These properties only exist before ejecting: ownPath: resolveOwn('.'), @@ -100,11 +110,15 @@ if (useTemplate) { appBuild: resolveOwn('../../build'), appPublic: resolveOwn('template/public'), appHtml: resolveOwn('template/public/index.html'), - appIndexJs: resolveOwn('template/src/index.js'), + appIndexJs: resolveOwn(`template/src/index${EXT}`), appPackageJson: resolveOwn('package.json'), appSrc: resolveOwn('template/src'), - testsSetup: resolveOwn('template/src/setupTests.js'), + testsSetup: resolveOwn(`template/src/setupTests${EXT}`), appNodeModules: resolveOwn('node_modules'), + appTsConfig: resolveOwn('template/tsconfig.json'), + appTsProdConfig: resolveOwn('template/tsconfig.prod.json'), + appTsLint: resolveOwn('template/tslint.json'), + appTsTestConfig: resolveOwn('template/tsconfig.test.json'), publicUrl: getPublicUrl(resolveOwn('package.json')), servedPath: getServedPath(resolveOwn('package.json')), // These properties only exist before ejecting: diff --git a/packages/react-scripts/config/webpack.config.dev.js b/packages/react-scripts/config/webpack.config.dev.js index 7a1b66803bc..f45efae1897 100644 --- a/packages/react-scripts/config/webpack.config.dev.js +++ b/packages/react-scripts/config/webpack.config.dev.js @@ -8,6 +8,7 @@ // @remove-on-eject-end 'use strict'; +const LANG = process.env.DEV_LANG; const autoprefixer = require('autoprefixer'); const path = require('path'); const webpack = require('webpack'); @@ -20,7 +21,8 @@ const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent'); const getClientEnvironment = require('./env'); const paths = require('./paths'); - +const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); +const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); // Webpack uses `publicPath` to determine where the app is being served from. // In development, we always serve from the root. This makes config easier. const publicPath = '/'; @@ -34,16 +36,24 @@ const env = getClientEnvironment(publicUrl); // Options for PostCSS as we reference these options twice // Adds vendor prefixing based on your specified browser support in // package.json +const postCSSLoaderPlugins = [ + require('postcss-flexbugs-fixes'), + autoprefixer({ + flexbox: 'no-2009' + }) +]; +if (env.raw.REACT_APP_REM_UNIT) { + postCSSLoaderPlugins.push( + require('postcss-px2rem')({ + remUnit: env.raw.REACT_APP_REM_UNIT + }) + ); +} const postCSSLoaderOptions = { // Necessary for external CSS imports to work // https://github.com/facebook/create-react-app/issues/2677 ident: 'postcss', - plugins: () => [ - require('postcss-flexbugs-fixes'), - autoprefixer({ - flexbox: 'no-2009', - }), - ], + plugins: postCSSLoaderPlugins }; // style files regexes @@ -58,12 +68,12 @@ const getStyleLoaders = (cssOptions, preProcessor) => { require.resolve('style-loader'), { loader: require.resolve('css-loader'), - options: cssOptions, + options: cssOptions }, { loader: require.resolve('postcss-loader'), - options: postCSSLoaderOptions, - }, + options: postCSSLoaderOptions + } ]; if (preProcessor) { loaders.push(require.resolve(preProcessor)); @@ -96,7 +106,7 @@ module.exports = { // require.resolve('webpack/hot/dev-server'), require.resolve('react-dev-utils/webpackHotDevClient'), // Finally, this is your app's code: - paths.appIndexJs, + paths.appIndexJs // We include the app code last so that if there is a runtime error during // initialization, it doesn't blow up the WebpackDevServer client, and // changing JS code would still trigger a refresh. @@ -114,7 +124,7 @@ module.exports = { publicPath: publicPath, // Point sourcemap entries to original disk location (format as URL on Windows) devtoolModuleFilenameTemplate: info => - path.resolve(info.absoluteResourcePath).replace(/\\/g, '/'), + path.resolve(info.absoluteResourcePath).replace(/\\/g, '/') }, resolve: { // This allows you to set a fallback for where Webpack should look for modules. @@ -131,7 +141,21 @@ module.exports = { // https://github.com/facebook/create-react-app/issues/290 // `web` extension prefixes have been added for better support // for React Native Web. - extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'], + extensions: + LANG === 'typescript' + ? [ + '.mjs', + '.web.ts', + '.ts', + '.web.tsx', + '.tsx', + '.web.js', + '.js', + '.json', + '.web.jsx', + '.jsx' + ] + : ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'], alias: { // @remove-on-eject-begin // Resolve Babel runtime relative to react-scripts. @@ -144,7 +168,7 @@ module.exports = { // @remove-on-eject-end // Support React Native Web // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ - 'react-native': 'react-native-web', + 'react-native': 'react-native-web' }, plugins: [ // Prevents users from importing files from outside of src/ (or node_modules/). @@ -152,8 +176,12 @@ 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, [paths.appPackageJson]), - ], + new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]) + ].concat( + LANG === 'typescript' + ? [new TsconfigPathsPlugin({ configFile: paths.appTsConfig })] + : [] + ) }, module: { strictExportPresence: true, @@ -167,23 +195,27 @@ module.exports = { test: /\.(js|jsx|mjs)$/, enforce: 'pre', use: [ - { - options: { - formatter: eslintFormatter, - eslintPath: require.resolve('eslint'), - baseConfig: { - extends: [require.resolve('eslint-config-react-app')], - }, - // @remove-on-eject-begin - ignore: false, - useEslintrc: false, - // @remove-on-eject-end - }, - loader: require.resolve('eslint-loader'), - }, + LANG === 'javascript' + ? { + options: { + formatter: eslintFormatter, + eslintPath: require.resolve('eslint'), + baseConfig: { + extends: [require.resolve('eslint-config-react-app')] + }, + // @remove-on-eject-begin + ignore: false, + useEslintrc: false + // @remove-on-eject-end + }, + loader: require.resolve('eslint-loader') + } + : { + loader: require.resolve('source-map-loader') + } ], include: paths.srcPaths, - exclude: [/[/\\\\]node_modules[/\\\\]/], + exclude: [/[/\\\\]node_modules[/\\\\]/] }, { // "oneOf" will traverse all following loaders until one will @@ -198,8 +230,8 @@ module.exports = { loader: require.resolve('url-loader'), options: { limit: 10000, - name: 'static/media/[name].[hash:8].[ext]', - }, + name: 'static/media/[name].[hash:8].[ext]' + } }, // Process application JS with Babel. // The preset includes JSX, Flow, and some ESnext features. @@ -218,26 +250,44 @@ module.exports = { babelrc: false, // @remove-on-eject-end presets: [require.resolve('babel-preset-react-app')], - plugins: [ - [ - require.resolve('babel-plugin-named-asset-import'), - { - loaderMap: { - svg: { - ReactComponent: 'svgr/webpack![path]', - }, - }, - }, - ], - ], // This is a feature of `babel-loader` for webpack (not Babel itself). // It enables caching results in ./node_modules/.cache/babel-loader/ // directory for faster rebuilds. cacheDirectory: true, - highlightCode: true, - }, + highlightCode: true + } + } + ] + }, + { + test: /\.(ts|tsx)$/, + include: paths.srcPaths, + exclude: [/[/\\\\]node_modules[/\\\\]/], + use: [ + // This loader parallelizes code compilation, it is optional but + // improves compile time on larger projects + // require.resolve('thread-loader'), + { + loader: require.resolve('babel-loader'), + options: { + // @remove-on-eject-begin + babelrc: false, + // @remove-on-eject-end + presets: [require.resolve('babel-preset-react-app')], + // This is a feature of `babel-loader` for webpack (not Babel itself). + // It enables caching results in ./node_modules/.cache/babel-loader/ + // directory for faster rebuilds. + cacheDirectory: true, + highlightCode: true + } }, - ], + { + loader: 'ts-loader', + options: { + transpileOnly: true + } + } + ] }, // Process any JS outside of the app with Babel. // Unlike the application JS, we only compile the standard ES features. @@ -253,13 +303,13 @@ module.exports = { babelrc: false, compact: false, presets: [ - require.resolve('babel-preset-react-app/dependencies'), + require.resolve('babel-preset-react-app/dependencies') ], cacheDirectory: true, - highlightCode: true, - }, - }, - ], + highlightCode: true + } + } + ] }, // "postcss" loader applies autoprefixer to our CSS. // "css" loader resolves paths in CSS and adds assets as dependencies. @@ -271,8 +321,8 @@ module.exports = { test: cssRegex, exclude: cssModuleRegex, use: getStyleLoaders({ - importLoaders: 1, - }), + importLoaders: 1 + }) }, // Adds support for CSS Modules (https://github.com/css-modules/css-modules) // using the extension .module.css @@ -281,8 +331,8 @@ module.exports = { use: getStyleLoaders({ importLoaders: 1, modules: true, - getLocalIdent: getCSSModuleLocalIdent, - }), + getLocalIdent: getCSSModuleLocalIdent + }) }, // Opt-in support for SASS (using .scss or .sass extensions). // Chains the sass-loader with the css-loader and the style-loader @@ -292,7 +342,7 @@ module.exports = { { test: sassRegex, exclude: sassModuleRegex, - use: getStyleLoaders({ importLoaders: 2 }, 'sass-loader'), + use: getStyleLoaders({ importLoaders: 2 }, 'sass-loader') }, // Adds support for CSS Modules, but using SASS // using the extension .module.scss or .module.sass @@ -302,15 +352,33 @@ module.exports = { { importLoaders: 2, modules: true, - getLocalIdent: getCSSModuleLocalIdent, + getLocalIdent: getCSSModuleLocalIdent }, 'sass-loader' - ), + ) + }, + { + test: /\.less$/, + exclude: sassModuleRegex, + use: getStyleLoaders({ importLoaders: 2 }, 'less-loader') + }, + // Adds support for CSS Modules, but using SASS + // using the extension .module.scss or .module.sass + { + test: /\.module\.less$/, + use: getStyleLoaders( + { + importLoaders: 2, + modules: true, + getLocalIdent: getCSSModuleLocalIdent + }, + 'less-loader' + ) }, // The GraphQL loader preprocesses GraphQL queries in .graphql files. { test: /\.(graphql)$/, - loader: 'graphql-tag/loader', + loader: 'graphql-tag/loader' }, // "file" loader makes sure those assets get served by WebpackDevServer. // When you `import` an asset, you get its (virtual) filename. @@ -325,14 +393,14 @@ module.exports = { exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/], loader: require.resolve('file-loader'), options: { - name: 'static/media/[name].[hash:8].[ext]', - }, - }, - ], - }, + name: 'static/media/[name].[hash:8].[ext]' + } + } + ] + } // ** STOP ** Are you adding a new loader? // Make sure to add the new loader(s) before the "file" loader. - ], + ] }, plugins: [ // Makes some environment variables available in index.html. @@ -343,7 +411,7 @@ module.exports = { // Generates an `index.html` file with the