diff --git a/README.md b/README.md index 2300fc11d..cfc021bd3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# `react-scripts-ts` [![npm version](https://badge.fury.io/js/react-scripts-ts.svg)](https://badge.fury.io/js/react-scripts-ts) [![Build Status](https://travis-ci.org/wmonk/create-react-app-typescript.svg?branch=master)](https://travis-ci.org/wmonk/create-react-app-typescript) +# `react-scripts-ts-sass` [![npm version](https://badge.fury.io/js/react-scripts-ts.svg)](https://badge.fury.io/js/react-scripts-ts) [![Build Status](https://travis-ci.org/wmonk/create-react-app-typescript.svg?branch=master)](https://travis-ci.org/wmonk/create-react-app-typescript) -Create React apps (with Typescript) with no build configuration. +Create React apps (with Typescript and Sass) with no build configuration. * [Getting Started](#tldr) – How to create a new app. * [User Guide](https://github.com/wmonk/create-react-app-typescript/blob/master/packages/react-scripts/template/README.md) – How to develop apps bootstrapped with react scripts ts. @@ -12,7 +12,7 @@ _Do you know react and want to try out typescript? Or do you know typescript and ```sh npm install -g create-react-app -create-react-app my-app --scripts-version=react-scripts-ts +create-react-app my-app --scripts-version=@petejkim/react-scripts-ts-sass cd my-app/ npm start ``` diff --git a/packages/react-scripts/config/webpack.config.dev.js b/packages/react-scripts/config/webpack.config.dev.js index 924e3e4f0..4881dfd2c 100644 --- a/packages/react-scripts/config/webpack.config.dev.js +++ b/packages/react-scripts/config/webpack.config.dev.js @@ -16,7 +16,6 @@ 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'); const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); @@ -175,11 +174,7 @@ module.exports = { include: paths.appSrc, use: [ { - loader: require.resolve('ts-loader'), - options: { - // disable type checker - we will use it in fork plugin - transpileOnly: true, - }, + loader: require.resolve('awesome-typescript-loader') }, ], }, @@ -220,6 +215,46 @@ module.exports = { }, ], }, + { + test: /\.(sass|scss)$/, + use: [ + require.resolve('style-loader'), + { + loader: require.resolve('css-loader'), + options: { + importLoaders: 1, + sourceMap: true, + }, + }, + { + loader: require.resolve('postcss-loader'), + options: { + // Necessary for external CSS imports to work + // https://github.com/facebookincubator/create-react-app/issues/2677 + ident: 'postcss', + plugins: () => [ + require('postcss-flexbugs-fixes'), + autoprefixer({ + browsers: [ + '>1%', + 'last 4 versions', + 'Firefox ESR', + 'not ie < 9', // React doesn't support IE8 anyway + ], + flexbox: 'no-2009', + }), + ], + sourceMap: true, + }, + }, + { + loader: require.resolve('sass-loader'), + options: { + sourceMap: true, + }, + }, + ], + }, // "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. @@ -274,14 +309,7 @@ module.exports = { // solution that requires the user to opt into importing specific locales. // 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({ - async: false, - watch: paths.appSrc, - tsconfig: paths.appTsConfig, - tslint: paths.appTsLint, - }), + new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/) ], // 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 7cb33afd0..e62630851 100644 --- a/packages/react-scripts/config/webpack.config.prod.js +++ b/packages/react-scripts/config/webpack.config.prod.js @@ -17,7 +17,6 @@ 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'); const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); @@ -247,6 +246,60 @@ module.exports = { ), // Note: this won't work without `new ExtractTextPlugin()` in `plugins`. }, + { + test: /\.(sass|scss)$/, + loader: ExtractTextPlugin.extract( + Object.assign( + { + fallback: { + loader: require.resolve('style-loader'), + options: { + hmr: false, + }, + }, + use: [ + { + loader: require.resolve('css-loader'), + options: { + importLoaders: 1, + minimize: true, + sourceMap: shouldUseSourceMap, + }, + }, + { + loader: require.resolve('postcss-loader'), + options: { + // Necessary for external CSS imports to work + // https://github.com/facebookincubator/create-react-app/issues/2677 + ident: 'postcss', + plugins: () => [ + require('postcss-flexbugs-fixes'), + autoprefixer({ + browsers: [ + '>1%', + 'last 4 versions', + 'Firefox ESR', + 'not ie < 9', // React doesn't support IE8 anyway + ], + flexbox: 'no-2009', + }), + ], + sourceMap: shouldUseSourceMap, + }, + }, + { + loader: require.resolve('sass-loader'), + options: { + sourceMap: shouldUseSourceMap, + }, + }, + ], + }, + extractTextPluginOptions + ) + ), + // Note: this won't work without `new ExtractTextPlugin()` in `plugins`. + }, // "file" loader makes sure assets end up in the `build` folder. // When you `import` an asset, you get its filename. // This loader doesn't use a "test" so it will catch all modules diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 95bf68c2a..e24e3a5c5 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,15 +1,12 @@ { - "name": "react-scripts-ts", + "name": "@petejkim/react-scripts-ts-sass", "version": "2.16.0", - "description": "Configuration and scripts for Create React App.", - "repository": "wmonk/create-react-app", + "description": "Configuration and scripts for Create React App with support for TypeScript and Sass.", + "repository": "petejkim/create-react-app-typescript-sass", "license": "BSD-3-Clause", "engines": { "node": ">=6" }, - "bugs": { - "url": "https://github.com/wmonk/create-react-app/issues" - }, "files": [ "bin", "config", @@ -22,6 +19,7 @@ }, "dependencies": { "autoprefixer": "7.1.6", + "awesome-typescript-loader": "4.0.1", "babel-jest": "^22.1.0", "babel-loader": "^7.1.2", "babel-preset-react-app": "^3.1.1", @@ -32,22 +30,22 @@ "dotenv-expand": "4.2.0", "extract-text-webpack-plugin": "3.0.2", "file-loader": "0.11.2", - "fork-ts-checker-webpack-plugin": "^0.2.8", "fs-extra": "3.0.1", "html-webpack-plugin": "2.29.0", "jest": "22.4.2", + "node-sass": "^4.7.2", "object-assign": "4.1.1", "postcss-flexbugs-fixes": "3.2.0", "postcss-loader": "2.0.8", "promise": "8.0.1", "raf": "3.4.0", - "source-map-loader": "^0.2.1", "react-dev-utils": "^5.0.1", "resolve": "1.6.0", + "sass-loader": "^7.0.1", + "source-map-loader": "^0.2.1", "style-loader": "0.19.0", "sw-precache-webpack-plugin": "0.11.4", "ts-jest": "22.0.1", - "ts-loader": "^2.3.7", "tsconfig-paths-webpack-plugin": "^2.0.0", "tslint": "^5.7.0", "tslint-config-prettier": "^1.10.0", diff --git a/packages/react-scripts/scripts/utils/createJestConfig.js b/packages/react-scripts/scripts/utils/createJestConfig.js index 515e56364..052543e91 100644 --- a/packages/react-scripts/scripts/utils/createJestConfig.js +++ b/packages/react-scripts/scripts/utils/createJestConfig.js @@ -35,8 +35,8 @@ module.exports = (resolve, rootDir, isEjecting) => { ? '/node_modules/babel-jest' : resolve('config/jest/babelTransform.js'), '^.+\\.tsx?$': resolve('config/jest/typescriptTransform.js'), - '^.+\\.css$': resolve('config/jest/cssTransform.js'), - '^(?!.*\\.(js|jsx|mjs|css|json)$)': resolve( + '^.+\\.(sass|scss|css)$': resolve('config/jest/cssTransform.js'), + '^(?!.*\\.(js|jsx|mjs|sass|scss|css|json)$)': resolve( 'config/jest/fileTransform.js' ), }, diff --git a/packages/react-scripts/template/src/App.css b/packages/react-scripts/template/src/App.css deleted file mode 100644 index c5c6e8a68..000000000 --- a/packages/react-scripts/template/src/App.css +++ /dev/null @@ -1,28 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - animation: App-logo-spin infinite 20s linear; - height: 80px; -} - -.App-header { - background-color: #222; - height: 150px; - padding: 20px; - color: white; -} - -.App-title { - font-size: 1.5em; -} - -.App-intro { - font-size: large; -} - -@keyframes App-logo-spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } -} diff --git a/packages/react-scripts/template/src/App.scss b/packages/react-scripts/template/src/App.scss new file mode 100644 index 000000000..6acf87173 --- /dev/null +++ b/packages/react-scripts/template/src/App.scss @@ -0,0 +1,28 @@ +.App { + text-align: center; + + &-logo { + animation: App-logo-spin infinite 20s linear; + height: 80px; + } + + &-header { + background-color: #222; + height: 150px; + padding: 20px; + color: white; + } + + &-title { + font-size: 1.5em; + } + + &-intro { + font-size: large; + } +} + +@keyframes App-logo-spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} diff --git a/packages/react-scripts/template/src/App.tsx b/packages/react-scripts/template/src/App.tsx index c1bc27ccd..26a5e8b29 100644 --- a/packages/react-scripts/template/src/App.tsx +++ b/packages/react-scripts/template/src/App.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import './App.css'; +import './App.scss'; import logo from './logo.svg'; diff --git a/packages/react-scripts/template/src/index.css b/packages/react-scripts/template/src/index.scss similarity index 100% rename from packages/react-scripts/template/src/index.css rename to packages/react-scripts/template/src/index.scss diff --git a/packages/react-scripts/template/src/index.tsx b/packages/react-scripts/template/src/index.tsx index a7b130622..5a6964bd1 100644 --- a/packages/react-scripts/template/src/index.tsx +++ b/packages/react-scripts/template/src/index.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom'; import App from './App'; -import './index.css'; +import './index.scss'; import registerServiceWorker from './registerServiceWorker'; ReactDOM.render(