diff --git a/.gitignore b/.gitignore index 79ce88915d7..da0b2163db7 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ npm-debug.log* yarn-debug.log* yarn-error.log* /.changelog +yarn.lock +.idea \ No newline at end of file diff --git a/README.md b/README.md index b09630e90ba..1fa8ebccd04 100644 --- a/README.md +++ b/README.md @@ -1,224 +1,100 @@ -# Create React App [![Build Status](https://travis-ci.org/facebookincubator/create-react-app.svg?branch=master)](https://travis-ci.org/facebookincubator/create-react-app) +### ๐Ÿ™‹โ€โ™‚๏ธ Made by [@thekitze](https://twitter.com/thekitze) -Create React apps with no build configuration. +### Other projects: +- ๐Ÿ’ป [Sizzy](https://sizzy.co) - A browser for designers and developers, focused on responsive design +- ๐Ÿซ [React Academy](https://reactacademy.io) - Interactive React and GraphQL workshops +- ๐Ÿ”ฎ [Glink](https://glink.so) - Changelogs, Roadmap, User Requests +- ๐Ÿถ [Benji](https://benji.so) - Ultimate wellness and productivity platform +- ๐Ÿค– [JSUI](https://github.com/kitze/JSUI) - A powerful UI toolkit for managing JavaScript apps +- ๐Ÿ“น [YouTube Vlog](https://youtube.com/kitze) - Follow my journey -* [Creating an App](#creating-an-app) โ€“ How to create a new app. -* [User Guide](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md) โ€“ How to develop apps bootstrapped with Create React App. +Zero To Shipped -Create React App works on macOS, Windows, and Linux.
-If something doesnโ€™t work, please [file an issue](https://github.com/facebookincubator/create-react-app/issues/new). +--- -## Quick Overview +โš ๏ธ This repo is **deprecated**. -```sh -npx create-react-app my-app -cd my-app -npm start -``` - -*([npx](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b) comes with npm 5.2+ and higher, see [instructions for older npm versions](https://gist.github.com/gaearon/4064d3c23a77c74a3614c498a8bb1c5f))* - -Then open [http://localhost:3000/](http://localhost:3000/) to see your app.
-When youโ€™re ready to deploy to production, create a minified bundle with `npm run build`. +Please use [react-app-rewired](https://github.com/timarney/react-app-rewired) if you want to customize CRA 1. +Please use [customize-cra](https://github.com/arackaf/customize-cra) if you want to customize CRA 2. -

- -

+# โ˜ข custom-react-scripts โ˜ข +Latest version of original react-scripts: **1.1.14** -### Get Started Immediately +### โš ๏ธ Disclaimer: +> This is **not** a fork of ```create-react-app```. It's just a fork of ```react-scripts``` with simple babel/webpack modifications that can toggle extra features. -You **donโ€™t** need to install or configure tools like Webpack or Babel.
-They are preconfigured and hidden so that you can focus on the code. +The reason for this fork's existence is explained better in [this Medium article](https://medium.com/@kitze/configure-create-react-app-without-ejecting-d8450e96196a). -Just create a project, and youโ€™re good to go. +### ๐Ÿ’กFeatures: +* Decorators +* babel-preset-stage-0 +* Less +* Sass +* CSS modules +* Sass modules +* Less modules +* Stylus modules -## Creating an App +**the features are optional and can be turned on/off individually* -**Youโ€™ll need to have Node >= 6 on your local development machine** (but itโ€™s not required on the server). You can use [nvm](https://github.com/creationix/nvm#installation) (macOS/Linux) or [nvm-windows](https://github.com/coreybutler/nvm-windows#node-version-manager-nvm-for-windows) to easily switch Node versions between different projects. +### โ”How to use it +```create-react-app my-app --scripts-version custom-react-scripts``` -To create a new app, run a single command: - -```sh -npx create-react-app my-app -``` +Modify the `.env` file in the root of the generated project, and add any of the configuration options below ๐Ÿ‘‡ to enable that feature. -*([npx](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b) comes with npm 5.2+ and higher, see [instructions for older npm versions](https://gist.github.com/gaearon/4064d3c23a77c74a3614c498a8bb1c5f))* +The generated project comes with every option turned on by default, but you can remove them at any time by removing the options from the ```.env``` file. -It will create a directory called `my-app` inside the current folder.
-Inside that directory, it will generate the initial project structure and install the transitive dependencies: +#### Adding to an existing project ``` -my-app -โ”œโ”€โ”€ README.md -โ”œโ”€โ”€ node_modules -โ”œโ”€โ”€ package.json -โ”œโ”€โ”€ .gitignore -โ”œโ”€โ”€ public -โ”‚ โ””โ”€โ”€ favicon.ico -โ”‚ โ””โ”€โ”€ index.html -โ”‚ โ””โ”€โ”€ manifest.json -โ””โ”€โ”€ src - โ””โ”€โ”€ App.css - โ””โ”€โ”€ App.js - โ””โ”€โ”€ App.test.js - โ””โ”€โ”€ index.css - โ””โ”€โ”€ index.js - โ””โ”€โ”€ logo.svg - โ””โ”€โ”€ registerServiceWorker.js +npm uninstall --save react-scripts; +npm install --save custom-react-scripts; ``` -No configuration or complicated folder structures, just the files you need to build your app.
-Once the installation is done, you can open your project folder: - -```sh -cd my-app -``` - -Inside the newly created project, you can run some built-in commands: - -### `npm start` or `yarn start` - -Runs the app in development mode.
-Open [http://localhost:3000](http://localhost:3000) to view it in the browser. - -The page will automatically reload if you make changes to the code.
-You will see the build errors and lint warnings in the console. - -Build errors - -### `npm test` or `yarn test` - -Runs the test watcher in an interactive mode.
-By default, runs tests related to files changed since the last commit. - -[Read more about testing.](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#running-tests) - -### `npm run build` or `yarn build` - -Builds the app for production to the `build` folder.
-It correctly bundles React in production mode and optimizes the build for the best performance. - -The build is minified and the filenames include the hashes.
-By default, it also [includes a service worker](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#making-a-progressive-web-app) so that your app loads from local cache on future visits. - -Your app is ready to be deployed. - -## User Guide - -The [User Guide](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md) includes information on different topics, such as: - -- [Updating to New Releases](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#updating-to-new-releases) -- [Folder Structure](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#folder-structure) -- [Available Scripts](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#available-scripts) -- [Supported Browsers](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#supported-browsers) -- [Supported Language Features and Polyfills](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#supported-language-features-and-polyfills) -- [Syntax Highlighting in the Editor](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#syntax-highlighting-in-the-editor) -- [Displaying Lint Output in the Editor](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#displaying-lint-output-in-the-editor) -- [Formatting Code Automatically](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#formatting-code-automatically) -- [Debugging in the Editor](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#debugging-in-the-editor) -- [Changing the Page ``](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#changing-the-page-title) -- [Installing a Dependency](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#installing-a-dependency) -- [Importing a Component](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#importing-a-component) -- [Code Splitting](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#code-splitting) -- [Adding a Stylesheet](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-a-stylesheet) -- [Post-Processing CSS](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#post-processing-css) -- [Adding a CSS Preprocessor (Sass, Less etc.)](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-a-css-preprocessor-sass-less-etc) -- [Adding Images, Fonts, and Files](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-images-fonts-and-files) -- [Using the `public` Folder](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#using-the-public-folder) -- [Using Global Variables](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#using-global-variables) -- [Adding Bootstrap](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-bootstrap) -- [Adding Flow](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-flow) -- [Adding a Router](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-a-router) -- [Adding Custom Environment Variables](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-custom-environment-variables) -- [Can I Use Decorators?](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#can-i-use-decorators) -- [Fetching Data with AJAX Requests](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#fetching-data-with-ajax-requests) -- [Integrating with an API Backend](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#integrating-with-an-api-backend) -- [Proxying API Requests in Development](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#proxying-api-requests-in-development) -- [Using HTTPS in Development](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#using-https-in-development) -- [Generating Dynamic `<meta>` Tags on the Server](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#generating-dynamic-meta-tags-on-the-server) -- [Pre-Rendering into Static HTML Files](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#pre-rendering-into-static-html-files) -- [Running Tests](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#running-tests) -- [Debugging Tests](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#debugging-tests) -- [Developing Components in Isolation](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#developing-components-in-isolation) -- [Publishing Components to npm](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#publishing-components-to-npm) -- [Making a Progressive Web App](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#making-a-progressive-web-app) -- [Analyzing the Bundle Size](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#analyzing-the-bundle-size) -- [Deployment](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#deployment) -- [Advanced Configuration](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#advanced-configuration) -- [Troubleshooting](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#troubleshooting) - -A copy of the user guide will be created as `README.md` in your project folder. - -## How to Update to New Versions? - -Please refer to the [User Guide](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#updating-to-new-releases) for this and other information. - -## Philosophy - -* **One Dependency:** There is just one build dependency. It uses Webpack, Babel, ESLint, and other amazing projects, but provides a cohesive curated experience on top of them. - -* **No Configuration Required:** You don't need to configure anything. Reasonably good configuration of both development and production builds is handled for you so you can focus on writing code. - -* **No Lock-In:** You can โ€œejectโ€ to a custom setup at any time. Run a single command, and all the configuration and build dependencies will be moved directly into your project, so you can pick up right where you left off. - -## Whatโ€™s Included? - -Your environment will have everything you need to build a modern single-page React app: - -* React, JSX, ES6, and Flow syntax support. -* Language extras beyond ES6 like the object spread operator. -* Autoprefixed CSS, so you donโ€™t need `-webkit` or other prefixes. -* A fast interactive unit test runner with built-in support for coverage reporting. -* A live development server that warns about common mistakes. -* A build script to bundle JS, CSS, and images for production, with hashes and sourcemaps. -* An offline-first [service worker](https://developers.google.com/web/fundamentals/getting-started/primers/service-workers) and a [web app manifest](https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/), meeting all the [Progressive Web App](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#making-a-progressive-web-app) criteria. -* Hassle-free updates for the above tools with a single dependency. - -Check out [this guide](https://github.com/nitishdayal/cra_closer_look) for an overview of how these tools fit together. - -The tradeoff is that **these tools are preconfigured to work in a specific way**. If your project needs more customization, you can ["eject"](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#npm-run-eject) and customize it, but then you will need to maintain this configuration. - -## Popular Alternatives - -Create React App is a great fit for: - -* **Learning React** in a comfortable and feature-rich development environment. -* **Starting new single-page React applications.** -* **Creating examples** with React for your libraries and components. - -Hereโ€™s a few common cases where you might want to try something else: - -* If you want to **try React** without hundreds of transitive build tool dependencies, consider [using a single HTML file or an online sandbox instead](https://reactjs.org/docs/try-react.html). +Add a `.env.` file with the desired features. -* If you need to **integrate React code with a server-side template framework** like Rails or Django, or if youโ€™re **not building a single-page app**, consider using [nwb](https://github.com/insin/nwb) or [Neutrino](https://neutrino.js.org/) which are more flexible. +### ๐Ÿ“ Configuration options -* If you need to **publish a React component**, [nwb](https://github.com/insin/nwb) can [also do this](https://github.com/insin/nwb#react-components-and-libraries), as well as [Neutrino's react-components preset](https://neutrino.js.org/packages/react-components/). +#### Styling +- ```REACT_APP_SASS=true``` - enable SASS support +- ```REACT_APP_LESS=true``` - enable LESS support +- ```REACT_APP_STYLUS=true``` - enable Stylus support +- ```REACT_APP_CSS_MODULES=true``` - enable CSS modules +- ```REACT_APP_SASS_MODULES=true``` - enable Sass modules +- ```REACT_APP_LESS_MODULES=true``` - enable Less modules +- ```REACT_APP_STYLUS_MODULES=true``` - enable Stylus modules +- ```REACT_APP_CSS_MODULE_CLASSNAME_TEMPLATE='module-[sha512:hash:base32]-[name]-[local]'``` - add custom CSS Module hash ident name -* If you want to do **server rendering** with React and Node.js, check out [Next.js](https://github.com/zeit/next.js/) or [Razzle](https://github.com/jaredpalmer/razzle). Create React App is agnostic of the backend, and just produces static HTML/JS/CSS bundles. +Note: to use modules the file must be named in the following format: ```$name.module.$preprocessorName```. -* If your website is **mostly static** (for example, a portfolio or a blog), consider using [Gatsby](https://www.gatsbyjs.org/) instead. Unlike Create React App, it pre-renders the website into HTML at the build time. +For example ```styles.module.css``` or ```header.module.sass``` or ```footer.module.less```, etc. Files that are not prefixed with module will be parsed normally. -* If you want to use **TypeScript**, consider using [create-react-app-typescript](https://github.com/wmonk/create-react-app-typescript). +#### Babel +- ```REACT_APP_BABEL_STAGE_0=true``` - enable stage-0 Babel preset +- ```REACT_APP_DECORATORS=true``` - enable decorators support -* Finally, if you need **more customization**, check out [Neutrino](https://neutrino.js.org/) and its [React preset](https://neutrino.js.org/packages/react/). +#### Other +- ```REACT_APP_WEBPACK_DASHBOARD=true``` - Enables connection to the [webpack-dashboard](https://github.com/FormidableLabs/electron-webpack-dashboard) Electron app (the app must be installed on local machine) -All of the above tools can work with little to no configuration. +### ๐Ÿค” Why? +The ```create-react-app``` app doesn't allow user configuration and modifications for few reasons: -If you prefer configuring the build yourself, [follow this guide](https://reactjs.org/docs/add-react-to-an-existing-app.html). +* Some of the babel presets and plugins that people might use are experimental. If they're used in a project and then they don't make it in the ES spec, they will break backwards compatibility. +* It's hard to maintain code for all of these custom configurations that people want to use. -## Contributing +But people still want to use some of these features, and they're either ejecting their CRA app, or just don't use ```create-react-app``` because they're *just* missing **X** feature. -We'd love to have your helping hand on `create-react-app`! See [CONTRIBUTING.md](CONTRIBUTING.md) for more information on what we're looking for and how to get started. +So instead of [searching npm](https://www.npmjs.com/search?q=react-scripts) for a ```react-scripts``` fork with the **X** feature you need, this fork provides support for all of these extra features with simply adding a line in the ```.env``` config. -## React Native +### How does it work? +The CRA team recently [added support](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-development-environment-variables-in-env) for an ```.env``` file in the root of the generated CRA project. -Looking for something similar, but for React Native?<br> -Check out [Create React Native App](https://github.com/react-community/create-react-native-app/). +From the original readme: +> To define permanent environment vairables, create a file called .env in the root of your project: +> ```REACT_APP_SECRET_CODE=abcdef``` -## Acknowledgements +I just added support for extra environment variables that actually turn on certain plugins, babel plugins, presets, and loaders in the webpack and babel configs of ```react-scripts```. -We are grateful to the authors of existing related projects for their ideas and collaboration: +### Future plans -* [@eanplatter](https://github.com/eanplatter) -* [@insin](https://github.com/insin) -* [@mxstbr](https://github.com/mxstbr) +I will put all of my efforts into supporting this fork to be always on par with features with the newest ```create-react-app``` and ```react-scripts``` versions. diff --git a/examples/.env b/examples/.env new file mode 100644 index 00000000000..0fba7f99c0d --- /dev/null +++ b/examples/.env @@ -0,0 +1,31 @@ +# delete the environment strings as appropriate + +# enable SASS support +REACT_APP_SASS=true + +# enable LESS support +REACT_APP_LESS=true + +# enable Stylus support +REACT_APP_STYLUS=true + +# enable CSS modules +REACT_APP_CSS_MODULES=true + +# enable Sass modules +REACT_APP_SASS_MODULES=true + +# enable Less modules +REACT_APP_LESS_MODULES=true + +# enable Stylus modules +REACT_APP_STYLUS_MODULES=true + +# enable stage-0 Babel preset +REACT_APP_BABEL_STAGE_0=true + +# enable decorators support +REACT_APP_DECORATORS=true + +# enable webpack dashboard access +REACT_APP_WEBPACK_DASHBOARD=true \ No newline at end of file diff --git a/packages/create-react-app/createReactApp.js b/packages/create-react-app/createReactApp.js index a2d9fdbd86b..0b60510cba6 100755 --- a/packages/create-react-app/createReactApp.js +++ b/packages/create-react-app/createReactApp.js @@ -481,7 +481,10 @@ function getPackageName(installPackage) { ); } else if (installPackage.match(/^file:/)) { const installPackagePath = installPackage.match(/^file:(.*)?$/)[1]; - const installPackageJson = require(path.join(installPackagePath, 'package.json')); + const installPackageJson = require(path.join( + installPackagePath, + 'package.json' + )); return Promise.resolve(installPackageJson.name); } return Promise.resolve(installPackage); diff --git a/packages/react-dev-utils/FileSizeReporter.js b/packages/react-dev-utils/FileSizeReporter.js index 68aae411f12..968e57c3932 100644 --- a/packages/react-dev-utils/FileSizeReporter.js +++ b/packages/react-dev-utils/FileSizeReporter.js @@ -43,7 +43,7 @@ function printFileSizesAfterBuild( name: path.basename(asset.name), size: size, sizeLabel: - filesize(size) + (difference ? ' (' + difference + ')' : '') + filesize(size) + (difference ? ' (' + difference + ')' : ''), }; }) ) diff --git a/packages/react-dev-utils/WebpackDevServerUtils.js b/packages/react-dev-utils/WebpackDevServerUtils.js index 4add9f9c1bc..1208d7fc776 100644 --- a/packages/react-dev-utils/WebpackDevServerUtils.js +++ b/packages/react-dev-utils/WebpackDevServerUtils.js @@ -318,7 +318,7 @@ function prepareProxy(proxy, appPublicFolder) { // However we also want to respect `proxy` for API calls. // So if `proxy` is specified as a string, we need to decide which fallback to use. // We use a heuristic: We want to proxy all the requests that are not meant - // for static assets and as all the requests for static assets will be using + // for static assets and as all the requests for static assets will be using // `GET` method, we can proxy all non-`GET` requests. // For `GET` requests, if request `accept`s text/html, we pick /index.html. // Modern browsers include text/html into `accept` header when navigating. diff --git a/packages/react-dev-utils/clearConsole.js b/packages/react-dev-utils/clearConsole.js index cb02af89237..2099a57ec35 100644 --- a/packages/react-dev-utils/clearConsole.js +++ b/packages/react-dev-utils/clearConsole.js @@ -8,7 +8,9 @@ 'use strict'; function clearConsole() { - process.stdout.write(process.platform === 'win32' ? '\x1B[2J\x1B[0f' : '\x1B[2J\x1B[3J\x1B[H'); + process.stdout.write( + process.platform === 'win32' ? '\x1B[2J\x1B[0f' : '\x1B[2J\x1B[3J\x1B[H' + ); } module.exports = clearConsole; diff --git a/packages/react-dev-utils/getProcessForPort.js b/packages/react-dev-utils/getProcessForPort.js index f9eda7752b4..8df45464977 100644 --- a/packages/react-dev-utils/getProcessForPort.js +++ b/packages/react-dev-utils/getProcessForPort.js @@ -58,7 +58,9 @@ function getProcessCommand(processId, processDirectory) { function getDirectoryOfProcessById(processId) { return execSync( - 'lsof -p ' + processId + ' | awk \'$4=="cwd" {for (i=9; i<=NF; i++) printf "%s ", $i}\'', + 'lsof -p ' + + processId + + ' | awk \'$4=="cwd" {for (i=9; i<=NF; i++) printf "%s ", $i}\'', execOptions ).trim(); } diff --git a/packages/react-dev-utils/launchEditor.js b/packages/react-dev-utils/launchEditor.js index cf190b08619..ddddb7930a7 100644 --- a/packages/react-dev-utils/launchEditor.js +++ b/packages/react-dev-utils/launchEditor.js @@ -56,8 +56,7 @@ const COMMON_EDITORS_OSX = { '/Applications/RubyMine.app/Contents/MacOS/rubymine', '/Applications/WebStorm.app/Contents/MacOS/webstorm': '/Applications/WebStorm.app/Contents/MacOS/webstorm', - '/Applications/MacVim.app/Contents/MacOS/MacVim': - 'mvim', + '/Applications/MacVim.app/Contents/MacOS/MacVim': 'mvim', }; const COMMON_EDITORS_LINUX = { diff --git a/packages/react-scripts/README.md b/packages/react-scripts/README.md index 8004b887004..44f88b61350 100644 --- a/packages/react-scripts/README.md +++ b/packages/react-scripts/README.md @@ -1,7 +1,72 @@ -# react-scripts +# โ˜ข custom-react-scripts โ˜ข +Latest version of original react-scripts: **1.1.14** -This package includes scripts and configuration used by [Create React App](https://github.com/facebookincubator/create-react-app).<br> -Please refer to its documentation: +### โš ๏ธ Disclaimer: +> This is **not** a fork of ```create-react-app```. It's just a fork of ```react-scripts``` with simple babel/webpack modifications that can toggle extra features. -* [Getting Started](https://github.com/facebookincubator/create-react-app/blob/master/README.md#getting-started) โ€“ How to create a new app. -* [User Guide](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md) โ€“ How to develop apps bootstrapped with Create React App. +The reason for this fork's existence is explained better in [this Medium article](https://medium.com/@kitze/configure-create-react-app-without-ejecting-d8450e96196a). + +### ๐Ÿ’กFeatures: +* Decorators +* babel-preset-stage-0 +* Less +* Sass +* CSS modules +* Sass modules +* Less modules +* Stylus modules + +**the features are optional and can be turned on/off individually* + +### โ”How to use it +```create-react-app my-app --scripts-version custom-react-scripts``` + +Modify the ```.env``` file in the root of the generated project, and add any of the configuration options below ๐Ÿ‘‡ to enable that feature. + +The generated project comes with every option turned on by default, but you can remove them at any time by removing the options from the ```.env``` file. + +### ๐Ÿ“ Configuration options + +#### Styling +- ```REACT_APP_SASS=true``` - enable SASS support +- ```REACT_APP_LESS=true``` - enable LESS support +- ```REACT_APP_STYLUS=true``` - enable Stylus support +- ```REACT_APP_CSS_MODULES``` - enable CSS modules +- ```REACT_APP_SASS_MODULES``` - enable Sass modules +- ```REACT_APP_LESS_MODULES``` - enable Less modules +- ```REACT_APP_STYLUS_MODULES``` - enable Stylus modules +- ```REACT_APP_CSS_MODULE_CLASSNAME_TEMPLATE='module-[sha512:hash:base32]-[name]-[local]'``` - add custom CSS Module hash ident name + +Note: to use modules the file must be named in the following format: ```$name.module.$preprocessorName```. + +For example ```styles.module.css``` or ```header.module.sass``` or ```footer.module.less```, etc. Files that are not prefixed with module will be parsed normally. + +#### Babel +- ```REACT_APP_BABEL_STAGE_0=true``` - enable stage-0 Babel preset +- ```REACT_APP_DECORATORS=true``` - enable decorators support + +#### Other +- ```REACT_APP_WEBPACK_DASHBOARD=true``` - Enables connection to the[webpack-dashboard](https://github.com/FormidableLabs/electron-webpack-dashboard) Electron app (the app must be installed on local machine) + +### ๐Ÿค” Why? +The ```create-react-app``` app doesn't allow user configuration and modifications for few reasons: + +* Some of the babel presets and plugins that people might use are experimental. If they're used in a project and then they don't make it in the ES spec, they will break backwards compatibility. +* It's hard to maintain code for all of these custom configurations that people want to use. + +But people still want to use some of these features, and they're either ejecting their CRA app, or just don't use ```create-react-app``` because they're *just* missing **X** feature. + +So instead of [searching npm](https://www.npmjs.com/search?q=react-scripts) for a ```react-scripts``` fork with the **X** feature you need, this fork provides support for all of these extra features with simply adding a line in the ```.env``` config. + +### How does it work? +The CRA team recently [added support](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-development-environment-variables-in-env) for an ```.env``` file in the root of the generated CRA project. + +From the original readme: +> To define permanent environment vairables, create a file called .env in the root of your project: +> ```REACT_APP_SECRET_CODE=abcdef``` + +I just added support for extra environment variables that actually turn on certain plugins, babel plugins, presets, and loaders in the webpack and babel configs of ```react-scripts```. + +### Future plans + +I will put all of my efforts into supporting this fork to be always on par with features with the newest ```create-react-app``` and ```react-scripts``` versions. \ No newline at end of file diff --git a/packages/react-scripts/bin/CUSTOM_README.md b/packages/react-scripts/bin/CUSTOM_README.md new file mode 100644 index 00000000000..1776dce86cf --- /dev/null +++ b/packages/react-scripts/bin/CUSTOM_README.md @@ -0,0 +1,65 @@ +# โ˜ข custom-react-scripts โ˜ข +Latest version of original react-scripts: **0.8.4** + +### โš ๏ธ Disclaimer: +> This is **not** a fork of ```create-react-app```. It's just a fork of ```react-scripts``` with simple babel/webpack modifications that can toggle extra features. + +The reason for this fork's existence is explained better in [this Medium article](https://medium.com/@kitze/configure-create-react-app-without-ejecting-d8450e96196a). + +### ๐Ÿ’กFeatures: +* Decorators +* babel-preset-stage-0 +* LESS +* SASS +* CSS modules + +**the features are optional and can be turned on/off individually* + +### โ”How to use it +```create-react-app my-app --scripts-version custom-react-scripts``` + +Modify the ```.env``` file in the root of the generated project, and add any of the configuration options below ๐Ÿ‘‡ to enable that feature. + +The generated project comes with SASS, LESS, and CSS modules support by default, but you can remove them at any time by removing the options from the ```.env``` file. + +### ๐Ÿ“ Configuration options + +#### Styling +- ```REACT_APP_SASS=true``` - enable SASS support +- ```REACT_APP_LESS=true``` - enable LESS support +- ```REACT_APP_STYLUS=true``` - enable Stylus support +- ```REACT_APP_CSS_MODULES``` - enable CSS modules + +#### Babel +- ```REACT_APP_BABEL_STAGE_0=true``` - enable stage-0 Babel preset +- ```REACT_APP_DECORATORS=true``` - enable decorators support + +> โš ๏ธ Please note that the Babel features are highly experimental (especially stage-0) and still not a part of the ES specification. +> Use them at your own risk of breaking backwards compatibility if they don't make the final version of the spec. + +#### Others +- ```PORT=3015``` - change default port (supported in CRA by default) +- ```OPEN_BROWSER=false``` - don't open browser after running webpack server + +### ๐Ÿค” Why? +The ```create-react-app``` app doesn't allow user configuration and modifications for few reasons: + +* Some of the babel presets and plugins that people might use are experimental. If they're used in a project and then they don't make it in the ES spec, they will break backwards compatibility. +* It's hard to maintain code for all of these custom configurations that people want to use. + +But people still want to use some of these features, and they're either ejecting their CRA app, or just don't use ```create-react-app``` because they're *just* missing **X** feature. + +So instead of [searching npm](https://www.npmjs.com/search?q=react-scripts) for a ```react-scripts``` fork with the **X** feature you need, this fork provides support for all of these extra features with simply adding a line in the ```.env``` config. + +### How does it work? +The CRA team recently [added support](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-development-environment-variables-in-env) for an ```.env``` file in the root of the generated CRA project. + +From the original readme: +> To define permanent environment vairables, create a file called .env in the root of your project: +> REACT_APP_SECRET_CODE=abcdef + +I just added support for extra environment variables that actually turn on certain plugins, babel plugins, presets, and loaders in the webpack and babel configs of ```react-scripts```. + +### Future plans + +I will put all of my efforts into supporting this fork to be always on par with features with the newest ```create-react-app``` and ```react-scripts``` versions. diff --git a/packages/react-scripts/config/custom-react-scripts/config.js b/packages/react-scripts/config/custom-react-scripts/config.js new file mode 100644 index 00000000000..25819dad1bc --- /dev/null +++ b/packages/react-scripts/config/custom-react-scripts/config.js @@ -0,0 +1,24 @@ +const mapObject = require('./utils/map-object'); + +const customizers = { + babelPlugins: require('./customizers/babel-plugins'), + babelPresets: require('./customizers/babel-presets'), + webpackLoaders: require('./customizers/webpack-loaders'), + webpackPlugins: require('./customizers/webpack-plugins'), +}; + +module.exports = getCustomConfig = (isDev = true) => { + var env = env || {}; + const result = mapObject(customizers, group => { + return mapObject( + group, + (customizer, key) => { + const envValue = process.env['REACT_APP_' + key]; + const activeEnvValue = env && envValue && envValue !== 'false'; + return (activeEnvValue || customizer.default) && customizer.get(isDev); + }, + true + ); + }); + return result; +}; diff --git a/packages/react-scripts/config/custom-react-scripts/customizers/babel-plugins.js b/packages/react-scripts/config/custom-react-scripts/customizers/babel-plugins.js new file mode 100644 index 00000000000..8650ecaee71 --- /dev/null +++ b/packages/react-scripts/config/custom-react-scripts/customizers/babel-plugins.js @@ -0,0 +1,5 @@ +module.exports = { + DECORATORS: { + get: () => require.resolve('babel-plugin-transform-decorators-legacy'), + }, +}; diff --git a/packages/react-scripts/config/custom-react-scripts/customizers/babel-presets.js b/packages/react-scripts/config/custom-react-scripts/customizers/babel-presets.js new file mode 100644 index 00000000000..1060a35c5b6 --- /dev/null +++ b/packages/react-scripts/config/custom-react-scripts/customizers/babel-presets.js @@ -0,0 +1,5 @@ +module.exports = { + BABEL_STAGE_0: { + get: () => require.resolve('babel-preset-stage-0'), + }, +}; diff --git a/packages/react-scripts/config/custom-react-scripts/customizers/webpack-loaders.js b/packages/react-scripts/config/custom-react-scripts/customizers/webpack-loaders.js new file mode 100644 index 00000000000..51094229fcd --- /dev/null +++ b/packages/react-scripts/config/custom-react-scripts/customizers/webpack-loaders.js @@ -0,0 +1,43 @@ +const styleLoader = require('../webpack-config/style-loader'); +const sassLoader = require.resolve('sass-loader'); +const lessLoader = require.resolve('less-loader'); +const stylusLoader = require.resolve('stylus-loader'); + +module.exports = { + CSS: { + default: true, + get: styleLoader(undefined, /\.css$/, /\.module\.css$/), + }, + SASS: { + get: styleLoader( + sassLoader, + /\.s[ac]ss$/, + /\.module\.s[ac]ss$/, + false, + { includePaths: ['./node_modules', './src'] } + ), + }, + LESS: { + get: styleLoader(lessLoader, /\.less$/, /\.module\.less$/), + }, + STYLUS: { + get: styleLoader(stylusLoader, /\.styl/, /\.module\.styl/), + }, + STYLUS_MODULES: { + get: styleLoader(stylusLoader, /\.module\.styl/, undefined, true), + }, + LESS_MODULES: { + get: styleLoader(lessLoader, /\.module\.less$/, undefined, true), + }, + SASS_MODULES: { + get: styleLoader( + sassLoader, + /\.module\.s[ac]ss$/, + undefined, + true, + { includePaths: ['./node_modules', './src'], }), + }, + CSS_MODULES: { + get: styleLoader(undefined, /\.module\.css$/, undefined, true), + }, +}; diff --git a/packages/react-scripts/config/custom-react-scripts/customizers/webpack-plugins.js b/packages/react-scripts/config/custom-react-scripts/customizers/webpack-plugins.js new file mode 100644 index 00000000000..58f9f6e90e6 --- /dev/null +++ b/packages/react-scripts/config/custom-react-scripts/customizers/webpack-plugins.js @@ -0,0 +1,7 @@ +const DashboardPlugin = require('webpack-dashboard/plugin'); + +module.exports = { + WEBPACK_DASHBOARD: { + get: () => new DashboardPlugin(), + }, +}; diff --git a/packages/react-scripts/config/custom-react-scripts/options/extract-text-plugin-options.js b/packages/react-scripts/config/custom-react-scripts/options/extract-text-plugin-options.js new file mode 100644 index 00000000000..c64d52dc3c9 --- /dev/null +++ b/packages/react-scripts/config/custom-react-scripts/options/extract-text-plugin-options.js @@ -0,0 +1,10 @@ +const paths = require('../../paths'); + +const publicPath = paths.servedPath; +const cssFilename = 'static/css/[name].[contenthash:8].css'; +const shouldUseRelativeAssetPaths = publicPath === './'; + +module.exports = shouldUseRelativeAssetPaths + ? // Making sure that the publicPath goes back to to build folder. + { publicPath: Array(cssFilename.split('/').length).join('../') } + : {}; diff --git a/packages/react-scripts/config/custom-react-scripts/options/postcss-options.js b/packages/react-scripts/config/custom-react-scripts/options/postcss-options.js new file mode 100644 index 00000000000..07c1a1278e1 --- /dev/null +++ b/packages/react-scripts/config/custom-react-scripts/options/postcss-options.js @@ -0,0 +1,12 @@ +const autoprefixer = require('autoprefixer'); + +module.exports = { + ident: 'postcss', + plugins: () => [ + require('postcss-flexbugs-fixes'), + autoprefixer({ + browsers: ['>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9'], + flexbox: 'no-2009', + }), + ], +}; diff --git a/packages/react-scripts/config/custom-react-scripts/utils/map-object.js b/packages/react-scripts/config/custom-react-scripts/utils/map-object.js new file mode 100644 index 00000000000..c60b072a031 --- /dev/null +++ b/packages/react-scripts/config/custom-react-scripts/utils/map-object.js @@ -0,0 +1,13 @@ +module.exports = function mapObject(obj, fn, toArray) { + return Object.keys(obj).reduce(function(final, key) { + var result = fn(obj[key], key); + if (!result) { + return final; + } + if (toArray) { + final.push(result); + } + final[key] = result; + return final; + }, toArray ? [] : {}); +}; diff --git a/packages/react-scripts/config/custom-react-scripts/webpack-config/style-loader.js b/packages/react-scripts/config/custom-react-scripts/webpack-config/style-loader.js new file mode 100644 index 00000000000..498aa00a031 --- /dev/null +++ b/packages/react-scripts/config/custom-react-scripts/webpack-config/style-loader.js @@ -0,0 +1,74 @@ +const postCssOptions = require('../options/postcss-options'); +const extractTextPluginOptions = require('../options/extract-text-plugin-options'); +const ExtractTextPlugin = require('extract-text-webpack-plugin'); +const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false'; +const localIdentName = + process.env.REACT_APP_CSS_MODULE_CLASSNAME_TEMPLATE || + '[sha512:hash:base32]-[name]-[local]'; + +module.exports = (loader, test, exclude, modules, options) => isDev => { + let loaders = isDev + ? [ + { + loader: require.resolve('style-loader'), + }, + ] + : []; + + loaders = loaders.concat([ + { + loader: require.resolve('css-loader'), + options: Object.assign( + { minimize: !isDev, sourceMap: shouldUseSourceMap }, + { importLoaders: 1 }, + modules === true + ? { + localIdentName: localIdentName, + modules: true, + } + : {} + ), + }, + { + loader: require.resolve('postcss-loader'), + options: Object.assign( + {}, + { sourceMap: shouldUseSourceMap }, + postCssOptions + ), + }, + ]); + + if (loader) { + loaders.push({ + loader, + options: Object.assign( + {}, + { sourceMap: shouldUseSourceMap }, + options + ), + }); + } + + if (isDev) { + return { + test, + exclude, + use: loaders, + }; + } + + return { + test, + exclude, + loader: ExtractTextPlugin.extract( + Object.assign( + { + fallback: require.resolve('style-loader'), + use: loaders, + }, + extractTextPluginOptions + ) + ), + }; +}; diff --git a/packages/react-scripts/config/jest/babelTransform.js b/packages/react-scripts/config/jest/babelTransform.js index 02742e90c6c..0f7111920b6 100644 --- a/packages/react-scripts/config/jest/babelTransform.js +++ b/packages/react-scripts/config/jest/babelTransform.js @@ -8,8 +8,15 @@ 'use strict'; const babelJest = require('babel-jest'); +const getCustomConfig = require('../custom-react-scripts/config'); + +//Get custom configuration for injecting plugins, presets and loaders +const customConfig = getCustomConfig(true); module.exports = babelJest.createTransformer({ - presets: [require.resolve('babel-preset-react-app')], + presets: [require.resolve('babel-preset-react-app')].concat( + customConfig.babelPresets + ), babelrc: false, + plugins: customConfig.babelPlugins, }); diff --git a/packages/react-scripts/config/webpack.config.dev.js b/packages/react-scripts/config/webpack.config.dev.js index 9f3131b0660..e6bc332a45b 100644 --- a/packages/react-scripts/config/webpack.config.dev.js +++ b/packages/react-scripts/config/webpack.config.dev.js @@ -8,7 +8,6 @@ // @remove-on-eject-end 'use strict'; -const autoprefixer = require('autoprefixer'); const path = require('path'); const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); @@ -19,6 +18,7 @@ const eslintFormatter = require('react-dev-utils/eslintFormatter'); const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); const getClientEnvironment = require('./env'); const paths = require('./paths'); +const getCustomConfig = require('./custom-react-scripts/config'); // Webpack uses `publicPath` to determine where the app is being served from. // In development, we always serve from the root. This makes config easier. @@ -29,6 +29,8 @@ const publicPath = '/'; const publicUrl = ''; // Get environment variables to inject into our app. const env = getClientEnvironment(publicUrl); +//Get custom configuration for injecting plugins, presets and loaders +const customConfig = getCustomConfig(true); // This is the development configuration. // It is focused on developer experience and fast rebuilds. @@ -166,53 +168,18 @@ module.exports = { include: paths.appSrc, loader: require.resolve('babel-loader'), options: { - // @remove-on-eject-begin babelrc: false, - presets: [require.resolve('babel-preset-react-app')], - // @remove-on-eject-end + presets: [require.resolve('babel-preset-react-app')].concat( + customConfig.babelPresets + ), + plugins: customConfig.babelPlugins, // 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, }, }, - // "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 <style> tags. - // In production, we use a plugin to extract that CSS to a file, but - // in development "style" loader enables hot editing of CSS. - { - test: /\.css$/, - use: [ - require.resolve('style-loader'), - { - loader: require.resolve('css-loader'), - options: { - importLoaders: 1, - }, - }, - { - 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', - }), - ], - }, - }, - ], - }, + ...customConfig.webpackLoaders, // "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. @@ -268,6 +235,7 @@ 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$/), + ...customConfig.webpackPlugins, ], // 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 3b2a2068db2..235b334ce70 100644 --- a/packages/react-scripts/config/webpack.config.prod.js +++ b/packages/react-scripts/config/webpack.config.prod.js @@ -8,7 +8,6 @@ // @remove-on-eject-end 'use strict'; -const autoprefixer = require('autoprefixer'); const path = require('path'); const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); @@ -20,13 +19,11 @@ const eslintFormatter = require('react-dev-utils/eslintFormatter'); const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); const paths = require('./paths'); const getClientEnvironment = require('./env'); +const getCustomConfig = require('./custom-react-scripts/config'); // Webpack uses `publicPath` to determine where the app is being served from. // It requires a trailing slash, or the file assets will get an incorrect path. const publicPath = paths.servedPath; -// Some apps do not use client-side routing with pushState. -// For these, "homepage" can be set to "." to enable relative asset paths. -const shouldUseRelativeAssetPaths = publicPath === './'; // Source maps are resource heavy and can cause out of memory issue for large source files. const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false'; // `publicUrl` is just like `publicPath`, but we will provide it to our app @@ -35,6 +32,8 @@ const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false'; const publicUrl = publicPath.slice(0, -1); // Get environment variables to inject into our app. const env = getClientEnvironment(publicUrl); +//Get custom configuration for injecting plugins, presets and loaders +const customConfig = getCustomConfig(false); // Assert this just to be safe. // Development builds of React are slow and not intended for production. @@ -45,15 +44,6 @@ if (env.stringified['process.env'].NODE_ENV !== '"production"') { // Note: defined here because it will be used more than once. const cssFilename = 'static/css/[name].[contenthash:8].css'; -// ExtractTextPlugin expects the build output to be flat. -// (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27) -// However, our output is structured with css, js and media folders. -// To have this structure working with relative paths, we have to use custom options. -const extractTextPluginOptions = shouldUseRelativeAssetPaths - ? // Making sure that the publicPath goes back to to build folder. - { publicPath: Array(cssFilename.split('/').length).join('../') } - : {}; - // This is the production configuration. // It compiles slowly and is focused on producing a fast and minimal bundle. // The development configuration is different and lives in a separate file. @@ -173,72 +163,15 @@ module.exports = { include: paths.appSrc, loader: require.resolve('babel-loader'), options: { - // @remove-on-eject-begin babelrc: false, - presets: [require.resolve('babel-preset-react-app')], - // @remove-on-eject-end + presets: [require.resolve('babel-preset-react-app')].concat( + customConfig.babelPresets + ), + plugins: customConfig.babelPlugins, compact: true, }, }, - // The notation here is somewhat confusing. - // "postcss" loader applies autoprefixer to our CSS. - // "css" loader resolves paths in CSS and adds assets as dependencies. - // "style" loader normally turns CSS into JS modules injecting <style>, - // but unlike in development configuration, we do something different. - // `ExtractTextPlugin` first applies the "postcss" and "css" loaders - // (second argument), then grabs the result CSS and puts it into a - // separate file in our build process. This way we actually ship - // a single CSS file in production instead of JS code injecting <style> - // tags. If you use code splitting, however, any async bundles will still - // use the "style" loader inside the async code so CSS from them won't be - // in the main CSS file. - { - test: /\.css$/, - 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', - }), - ], - }, - }, - ], - }, - extractTextPluginOptions - ) - ), - // Note: this won't work without `new ExtractTextPlugin()` in `plugins`. - }, + ...customConfig.webpackLoaders, // "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 c33c3b4b5c4..dbf1f6b65ed 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,14 +1,14 @@ { - "name": "react-scripts", - "version": "1.1.4", - "description": "Configuration and scripts for Create React App.", - "repository": "facebookincubator/create-react-app", + "name": "custom-react-scripts", + "version": "0.2.3", + "description": "Configuration and scripts for create-react-app", + "repository": "kitze/custom-react-scripts", "license": "MIT", "engines": { "node": ">=6" }, "bugs": { - "url": "https://github.com/facebookincubator/create-react-app/issues" + "url": "https://github.com/kitze/custom-react-scripts/issues" }, "files": [ "bin", @@ -26,7 +26,9 @@ "babel-eslint": "7.2.3", "babel-jest": "20.0.3", "babel-loader": "7.1.2", + "babel-plugin-transform-decorators-legacy": "^1.3.4", "babel-preset-react-app": "^3.1.1", + "babel-preset-stage-0": "^6.24.1", "babel-runtime": "6.26.0", "case-sensitive-paths-webpack-plugin": "2.1.1", "chalk": "1.1.3", @@ -44,18 +46,27 @@ "file-loader": "1.1.5", "fs-extra": "3.0.1", "html-webpack-plugin": "2.29.0", + "identity-obj-proxy": "^3.0.0", "jest": "20.0.4", + "less": "^2.7.2", + "less-loader": "^4.0.5", + "node-sass": "^4.5.3", "object-assign": "4.1.1", "postcss-flexbugs-fixes": "3.2.0", "postcss-loader": "2.0.8", "promise": "8.0.1", "raf": "3.4.0", "react-dev-utils": "^5.0.1", + "react-error-overlay": "^1.0.10", "resolve": "1.6.0", + "sass-loader": "^6.0.6", "style-loader": "0.19.0", + "stylus": "^0.54.5", + "stylus-loader": "^3.0.1", "sw-precache-webpack-plugin": "0.11.4", "url-loader": "0.6.2", "webpack": "3.8.1", + "webpack-dashboard": "^1.0.0-2", "webpack-dev-server": "2.9.4", "webpack-manifest-plugin": "1.3.2", "whatwg-fetch": "2.0.3" diff --git a/packages/react-scripts/scripts/build.js b/packages/react-scripts/scripts/build.js index 930897008e1..ad05038dbbe 100644 --- a/packages/react-scripts/scripts/build.js +++ b/packages/react-scripts/scripts/build.js @@ -100,6 +100,8 @@ measureFileSizesBeforeBuild(paths.appBuild) buildFolder, useYarn ); + + process.exit(); }, err => { console.log(chalk.red('Failed to compile.\n')); diff --git a/packages/react-scripts/scripts/eject.js b/packages/react-scripts/scripts/eject.js index c8438f5d156..d8901f7bc3d 100644 --- a/packages/react-scripts/scripts/eject.js +++ b/packages/react-scripts/scripts/eject.js @@ -86,7 +86,16 @@ inquirer } } - const folders = ['config', 'config/jest', 'scripts']; + const folders = [ + 'config', + 'config/jest', + 'config/custom-react-scripts', + 'config/custom-react-scripts/customizers', + 'config/custom-react-scripts/options', + 'config/custom-react-scripts/utils', + 'config/custom-react-scripts/webpack-config', + 'scripts', + ]; // Make shallow array of files paths const files = folders.reduce((files, folder) => { diff --git a/packages/react-scripts/scripts/getProcessForPort.js b/packages/react-scripts/scripts/getProcessForPort.js new file mode 100644 index 00000000000..5540fbad47a --- /dev/null +++ b/packages/react-scripts/scripts/getProcessForPort.js @@ -0,0 +1,61 @@ +var chalk = require('chalk'); +var execSync = require('child_process').execSync; +var path = require('path'); + +var execOptions = { + encoding: 'utf8', + stdio: [ + 'pipe', // stdin (default) + 'pipe', // stdout (default) + 'ignore' //stderr + ] +}; + +function isProcessAReactApp(processCommand) { + return /^node .*react-scripts\/scripts\/start\.js\s?$/.test(processCommand); +} + +function getProcessIdOnPort(port) { + return execSync('lsof -i:' + port + ' -P -t -sTCP:LISTEN', execOptions).trim(); +} + +function getPackageNameInDirectory(directory) { + var packagePath = path.join(directory.trim(), 'package.json'); + + try { + return require(packagePath).name; + } catch(e) { + return null; + } + +} + +function getProcessCommand(processId, processDirectory) { + var command = execSync('ps -o command -p ' + processId + ' | sed -n 2p', execOptions); + + if (isProcessAReactApp(command)) { + const packageName = getPackageNameInDirectory(processDirectory); + return (packageName) ? packageName + '\n' : command; + } else { + return command; + } + +} + +function getDirectoryOfProcessById(processId) { + return execSync('lsof -p '+ processId + ' | grep cwd | awk \'{print $9}\'', execOptions).trim(); +} + +function getProcessForPort(port) { + try { + var processId = getProcessIdOnPort(port); + var directory = getDirectoryOfProcessById(processId); + var command = getProcessCommand(processId, directory); + return chalk.cyan(command) + chalk.blue(' in ') + chalk.cyan(directory); + } catch(e) { + return null; + } +} + +module.exports = getProcessForPort; + diff --git a/packages/react-scripts/scripts/modify-readmes.js b/packages/react-scripts/scripts/modify-readmes.js new file mode 100644 index 00000000000..bb3a36d8ab1 --- /dev/null +++ b/packages/react-scripts/scripts/modify-readmes.js @@ -0,0 +1,74 @@ +var fs = require('fs-extra'); +var path = require('path'); +const args = process.argv; + +//read md file as text +require.extensions['.md'] = function (module, filename) { + module.exports = fs.readFileSync(filename, 'utf8'); +}; + +var filenames = { + BACKUP: 'README_BACKUP.md', + README: 'README.MD', + CUSTOM_README: 'CUSTOM_README.md' +}; + +var paths = { + //original + RSreadme: path.join(__dirname, '..', filenames.README), + CRAreadme: path.join(__dirname, '../../../', filenames.README), + //custom + customReadme: path.join(__dirname, '../bin/', filenames.CUSTOM_README), + //backup + RSbackup: path.join(__dirname, '..', filenames.BACKUP), + CRAbackup: path.join(__dirname, '../../../', filenames.BACKUP) +}; + +function backupOriginal() { + fs.copySync(paths.RSreadme, paths.RSbackup); + fs.copySync(paths.CRAreadme, paths.CRAbackup); +} + +function deleteBackup() { + fs.removeSync(paths.RSbackup); + fs.removeSync(paths.CRAbackup); +} + +function deleteOriginal() { + fs.removeSync(paths.RSreadme); + fs.removeSync(paths.CRAreadme); +} + +function placeCustom() { + fs.copySync(paths.customReadme, paths.RSreadme); + fs.copySync(paths.customReadme, paths.CRAreadme); +} + +function placeOriginal() { + fs.copySync(paths.RSbackup, paths.RSreadme); + fs.copySync(paths.CRAbackup, paths.CRAreadme); +} + +//will set custom readmes +function setCustom() { + backupOriginal(); + deleteOriginal(); + placeCustom(); +} + +//will revert original readmes +function revertOriginalBackups() { + deleteOriginal(); + placeOriginal(); + deleteBackup(); +} + +var argFunctionMap = { + '--custom': setCustom, + '--original': revertOriginalBackups, +} + +if (args && args.length >= 2) { + var command = argFunctionMap[args[2]]; + command && command(); +} \ No newline at end of file diff --git a/packages/react-scripts/scripts/utils/createJestConfig.js b/packages/react-scripts/scripts/utils/createJestConfig.js index 4c428004a84..b85436165f4 100644 --- a/packages/react-scripts/scripts/utils/createJestConfig.js +++ b/packages/react-scripts/scripts/utils/createJestConfig.js @@ -42,6 +42,7 @@ module.exports = (resolve, rootDir, isEjecting) => { transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs)$'], moduleNameMapper: { '^react-native$': 'react-native-web', + '\\.(s?css|styl|less)$': 'identity-obj-proxy', }, moduleFileExtensions: [ 'web.js', diff --git a/packages/react-scripts/template/.env b/packages/react-scripts/template/.env new file mode 100644 index 00000000000..ecc4ab94047 --- /dev/null +++ b/packages/react-scripts/template/.env @@ -0,0 +1,16 @@ +REACT_APP_DECORATORS = true; +REACT_APP_BABEL_STAGE_0 = true; + +REACT_APP_SASS = true; +REACT_APP_LESS = true; +REACT_APP_STYLUS = true; + +REACT_APP_CSS_MODULES = true; +REACT_APP_SASS_MODULES = true; +REACT_APP_STYLUS_MODULES = true; +REACT_APP_LESS_MODULES = true; + +REACT_APP_WEBPACK_DASHBOARD = true; + +# CSS Module hash +# REACT_APP_CSS_MODULE_CLASSNAME_TEMPLATE = 'module-[sha512:hash:base32]-[name]-[local]'; diff --git a/packages/react-scripts/template/src/App.css b/packages/react-scripts/template/src/App.css old mode 100644 new mode 100755 diff --git a/packages/react-scripts/template/src/App.js b/packages/react-scripts/template/src/App.js index 203067e4d75..40959b6a132 100644 --- a/packages/react-scripts/template/src/App.js +++ b/packages/react-scripts/template/src/App.js @@ -1,18 +1,123 @@ import React, { Component } from 'react'; import logo from './logo.svg'; -import './App.css'; + +//components +import Emoji from './Emoji'; + +//styles +import './App.scss'; +import './App.less'; +import './App.styl'; + +//modules +import cssStyles from './First.module.css'; +import sassStyles from './Second.module.scss'; +import lessStyles from './Third.module.less'; +import stylusStyles from './Fourth.module.styl'; class App extends Component { render() { return ( <div className="App"> - <header className="App-header"> + <header className={cssStyles.header}> <img src={logo} className="App-logo" alt="logo" /> - <h1 className="App-title">Welcome to React</h1> + <h2 className="App-title"> + <Emoji label="danger" emoji="โ˜ข" /> + <span> custom-react-scripts </span> + <Emoji label="danger" emoji="โ˜ข" /> + </h2> + <div className="App-subtitle"> + allow custom config for create-react-app without ejecting + </div> </header> - <p className="App-intro"> - To get started, edit <code>src/App.js</code> and save to reload. - </p> + + <div className={stylusStyles.description}> + <div className={sassStyles.command}> + <code> + create-react-app my-app --scripts-version custom-react-scripts + </code> + </div> + + <p> + If you want to enable/disable certain features just modify the + <b> .env</b> file in the root directory of the project. + </p> + + <b> Styling </b> + <ul className="configs style-configs"> + <li> + <code>REACT_APP_SASS=true</code> + <span>- Enable SASS</span> + </li> + <li> + <code>REACT_APP_LESS=true</code> + <span>- Enable LESS</span> + </li> + <li> + <code>REACT_APP_STYLUS=true</code> + <span>- Enable Stylus</span> + </li> + <li> + <code>REACT_APP_CSS_MODULES=true</code> + <span>- Enable CSS modules </span> + </li> + <li> + <code>REACT_APP_SASS_MODULES=true</code> + <span>- Enable Sass modules </span> + </li> + <li> + <code>REACT_APP_SASS_MODULES=true</code> + <span>- Enable Stylus modules </span> + </li> + <li> + <code>REACT_APP_SASS_MODULES=true</code> + <span>- Enable Less modules </span> + </li> + </ul> + + <b>Babel</b> + + <ul className="configs babel-configs"> + <li> + <code>REACT_APP_BABEL_STAGE_0=true</code> + <span>- Enable stage-0 preset</span> + </li> + <li> + <code>REACT_APP_DECORATORS=true</code> + <span>- Enable usage of decorators</span> + </li> + </ul> + + <b>Other</b> + + <ul className="configs babel-configs"> + <li> + <code>REACT_APP_WEBPACK_DASHBOARD=true</code> + <span> + - Enables connection to {' '} + <a + target="_blank" + rel="noopener noreferrer" + href="https://github.com/FormidableLabs/electron-webpack-dashboard" + > + webpack-dashboard + </a>{' '} + (must be installed) + </span> + </li> + </ul> + + <br /> + <br /> + <a + target="_blank" + rel="noopener noreferrer" + className={lessStyles.readmeLink} + href="https://github.com/kitze/create-react-app/tree/master/packages/react-scripts" + > + Link to full README.md + </a> + </div> </div> ); } diff --git a/packages/react-scripts/template/src/App.less b/packages/react-scripts/template/src/App.less new file mode 100644 index 00000000000..f1d54ecb419 --- /dev/null +++ b/packages/react-scripts/template/src/App.less @@ -0,0 +1,10 @@ +.App { + &-title { + justify-content: center; + } + + &-subtitle { + font-weight: 100; + } + +} \ No newline at end of file diff --git a/packages/react-scripts/template/src/App.scss b/packages/react-scripts/template/src/App.scss new file mode 100644 index 00000000000..1348208d060 --- /dev/null +++ b/packages/react-scripts/template/src/App.scss @@ -0,0 +1,15 @@ +.configs { + li { + margin: 15px 0px; + } +} + +code { + border-radius: 3px; + padding: 2px 10px; + font-size: 17px; + margin-right: 10px; + background-color: rgba(222, 222, 222, 0.34); + border: 1px solid #cccccc; + color: #868686; +} diff --git a/packages/react-scripts/template/src/App.styl b/packages/react-scripts/template/src/App.styl new file mode 100644 index 00000000000..0c31ffb0d3a --- /dev/null +++ b/packages/react-scripts/template/src/App.styl @@ -0,0 +1,9 @@ +.App-logo + animation App-logo-spin infinite 20s linear + height 80px + +@keyframes App-logo-spin + from + transform rotate(0deg) + to + transform rotate(360deg) \ No newline at end of file diff --git a/packages/react-scripts/template/src/Emoji.js b/packages/react-scripts/template/src/Emoji.js new file mode 100644 index 00000000000..44139953562 --- /dev/null +++ b/packages/react-scripts/template/src/Emoji.js @@ -0,0 +1,6 @@ +import React from 'react'; + +export default ({ emoji, label }) => + <span aria-label={label} role="img"> + {emoji} + </span>; diff --git a/packages/react-scripts/template/src/First.module.css b/packages/react-scripts/template/src/First.module.css new file mode 100644 index 00000000000..5ed303f6846 --- /dev/null +++ b/packages/react-scripts/template/src/First.module.css @@ -0,0 +1,7 @@ +.header { + background-color: #222; + height: 180px; + padding: 20px; + color: white; + text-align: center; +} \ No newline at end of file diff --git a/packages/react-scripts/template/src/Fourth.module.styl b/packages/react-scripts/template/src/Fourth.module.styl new file mode 100644 index 00000000000..cdbf8250c29 --- /dev/null +++ b/packages/react-scripts/template/src/Fourth.module.styl @@ -0,0 +1,2 @@ +.description + padding 20px \ No newline at end of file diff --git a/packages/react-scripts/template/src/Second.module.scss b/packages/react-scripts/template/src/Second.module.scss new file mode 100644 index 00000000000..7c7e2ecfa39 --- /dev/null +++ b/packages/react-scripts/template/src/Second.module.scss @@ -0,0 +1,3 @@ +.command { + margin: 40px 0px 50px 0; +} \ No newline at end of file diff --git a/packages/react-scripts/template/src/Third.module.less b/packages/react-scripts/template/src/Third.module.less new file mode 100644 index 00000000000..e45874e7d88 --- /dev/null +++ b/packages/react-scripts/template/src/Third.module.less @@ -0,0 +1,3 @@ +.readmeLink { + font-size: 18px; +} \ No newline at end of file diff --git a/tasks/replace-own-deps.js b/tasks/replace-own-deps.js index 9178b01029e..0708f00d79d 100755 --- a/tasks/replace-own-deps.js +++ b/tasks/replace-own-deps.js @@ -16,13 +16,13 @@ const packagesDir = path.join(__dirname, '../packages'); const pkgFilename = path.join(packagesDir, 'react-scripts/package.json'); const data = require(pkgFilename); -fs.readdirSync(packagesDir).forEach((name) => { +fs.readdirSync(packagesDir).forEach(name => { if (data.dependencies[name]) { data.dependencies[name] = 'file:' + path.join(packagesDir, name); } -}) +}); -fs.writeFile(pkgFilename, JSON.stringify(data, null, 2), 'utf8', (err) => { +fs.writeFile(pkgFilename, JSON.stringify(data, null, 2), 'utf8', err => { if (err) throw err; console.log('Replaced local dependencies.'); });