diff --git a/README.md b/README.md
index 881ba7f4ad5..5b688f4f5cc 100644
--- a/README.md
+++ b/README.md
@@ -1,203 +1,45 @@
-# Create React App [](https://travis-ci.org/facebook/create-react-app) [](https://github.com/facebook/create-react-app/pulls)
+# create-react-app with support for Rust [](https://travis-ci.org/facebook/create-react-app) [](https://github.com/facebook/create-react-app/pulls)
-Create React apps with no build configuration.
+This project is a fork of Facebook's [create-react-app](https://facebook.github.io/create-react-app/) with support for Rust that compiles to WebAssembly.
- [Creating an App](#creating-an-app) – How to create a new app.
- [User Guide](https://facebook.github.io/create-react-app/) – How to develop apps bootstrapped with Create React App.
-Create React App works on macOS, Windows, and Linux.
+Create React App works on macOS, Windows, and Linux. However Rust tools may behave diferently on Windows in certain circumstances.
+
If something doesn’t work, please [file an issue](https://github.com/facebook/create-react-app/issues/new).
## Quick Overview
-```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`.
-
-
-
-
-
-### Get Started Immediately
-
-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.
-
-Just create a project, and you’re good to go.
-
-## Creating an App
-
-**You’ll need to have Node 8.10.0 or later 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.
-
-To create a new app, you may choose one of the following methods:
-
-### npx
+If you haven't already you'll need to install Rust and source it into your current context
```sh
-npx create-react-app my-app
+curl https://sh.rustup.rs -sSf | sh
+source $HOME/.cargo/env
```
-_([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))_
-
-### npm
-
-```sh
-npm init react-app my-app
-```
-
-_`npm init ` is available in npm 6+_
-
-### Yarn
-
-```sh
-yarn create react-app my-app
-```
-
-_`yarn create` is available in Yarn 0.25+_
-
-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:
-
-```
-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
- └── serviceWorker.js
-```
-
-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:
+Then you can run the tool with `npx`
```sh
+npx create-react-app my-app --scripts-version react-scripts-rust
cd my-app
+npm start
```
-Inside the newly created project, you can run some built-in commands:
-
-### `npm start` or `yarn 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))_
-Runs the app in development mode.
-Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
+Then open [http://localhost:3000/](http://localhost:3000/) to see your app.
-The page will automatically reload if you make changes to the code.
-You will see the build errors and lint warnings in the console.
+When you’re ready to deploy to production, create a minified bundle with `npm run build`.
-
+
-### `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://facebook.github.io/create-react-app/docs/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.
-
-Your app is ready to be deployed.
-
-## User Guide
-
-You can find detailed instructions on using Create React App and many tips in [its documentation](https://facebook.github.io/create-react-app/).
-
-## How to Update to New Versions?
-
-Please refer to the [User Guide](https://facebook.github.io/create-react-app/docs/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. A 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, TypeScript 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://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) criteria. (_Note: Using the service worker is opt-in as of `react-scripts@2.0.0` and higher_)
-- 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://facebook.github.io/create-react-app/docs/available-scripts#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 are 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).
-
-- If you need to **integrate React code with a server-side template framework** like Rails, Django or Symfony, 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. For Rails specifically, you can use [Rails Webpacker](https://github.com/rails/webpacker). For Symfony, try [Symfony's Webpack Encore](https://symfony.com/doc/current/frontend/encore/reactjs.html).
-
-- 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/).
-
-- 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.
-
-- 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.
-
-- Finally, if you need **more customization**, check out [Neutrino](https://neutrino.js.org/) and its [React preset](https://neutrino.js.org/packages/react/).
-
-All of the above tools can work with little to no configuration.
-
-If you prefer configuring the build yourself, [follow this guide](https://reactjs.org/docs/add-react-to-an-existing-app.html).
-
-## Contributing
-
-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.
-
-## React Native
-
-Looking for something similar, but for React Native?
-Check out [Expo CLI](https://github.com/expo/expo-cli).
-
-## Acknowledgements
-
-We are grateful to the authors of existing related projects for their ideas and collaboration:
-
-- [@eanplatter](https://github.com/eanplatter)
-- [@insin](https://github.com/insin)
-- [@mxstbr](https://github.com/mxstbr)
+## Vision
-## License
+The following articles inspired the effort to combine rust, React, and WebAssembly:
-Create React App is open source software [licensed as MIT](https://github.com/facebook/create-react-app/blob/master/LICENSE).
+- https://users.rust-lang.org/t/native-webassembly-loader-for-webpack/14407
+- https://github.com/yamafaktory/rust-wasm-webpack
+- https://www.hellorust.com/demos/add/index.html
diff --git a/packages/react-scripts/README.md b/packages/react-scripts/README.md
index d6de290ff05..35af4995aed 100644
--- a/packages/react-scripts/README.md
+++ b/packages/react-scripts/README.md
@@ -1,7 +1,24 @@
-# react-scripts
+# react-scripts-rust
-This package includes scripts and configuration used by [Create React App](https://github.com/facebook/create-react-app).
+This package includes scripts and configuration used by [Create React App (Rust)](https://github.com/thomashorrobin/create-react-app-rust).
Please refer to its documentation:
- [Getting Started](https://facebook.github.io/create-react-app/docs/getting-started) – How to create a new app.
- [User Guide](https://facebook.github.io/create-react-app/) – How to develop apps bootstrapped with Create React App.
+
+
+## Quick Overview
+
+First install Rust if you haven't already
+```sh
+curl https://sh.rustup.rs -sSf | sh
+source $HOME/.cargo/env
+```
+Then you can run the tool with `npx`
+```sh
+npx create-react-app my-app --scripts-version react-scripts-rust
+cd my-app
+npm start
+```
+
+After the project has loaded in Chrome any changes in `src/lib.rs` should result in an instant update in the browser.
diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js
index 746884a03eb..ee3fc046ae3 100644
--- a/packages/react-scripts/config/webpack.config.js
+++ b/packages/react-scripts/config/webpack.config.js
@@ -325,6 +325,21 @@ module.exports = function(webpackEnv) {
],
include: paths.appSrc,
},
+ {
+ test: /\.rs$/,
+ use: [
+ {
+ loader: 'wasm-loader',
+ },
+ {
+ loader: 'rust-native-wasm-loader',
+ options: {
+ release: true,
+ gc: true,
+ },
+ },
+ ],
+ },
{
// "oneOf" will traverse all following loaders until one will
// match the requirements. When no loader matches it will fall
diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json
index 1f6b8cfafec..b196df58955 100644
--- a/packages/react-scripts/package.json
+++ b/packages/react-scripts/package.json
@@ -1,14 +1,14 @@
{
- "name": "react-scripts",
- "version": "2.1.1",
- "description": "Configuration and scripts for Create React App.",
- "repository": "facebook/create-react-app",
+ "name": "react-scripts-rust",
+ "version": "2.0.17",
+ "description": "Configuration and scripts for using Rust with Create React App",
+ "repository": "thomashorrobin/create-react-app-rust",
"license": "MIT",
"engines": {
"node": ">=6"
},
"bugs": {
- "url": "https://github.com/facebook/create-react-app/issues"
+ "url": "https://github.com/thomashorrobin/create-react-app-rust/issues"
},
"files": [
"bin",
@@ -35,6 +35,7 @@
"bfj": "6.1.1",
"case-sensitive-paths-webpack-plugin": "2.1.2",
"chalk": "2.4.1",
+ "command-exists": "^1.2.8",
"css-loader": "1.0.0",
"dotenv": "6.0.0",
"dotenv-expand": "4.2.0",
@@ -63,10 +64,13 @@
"react-app-polyfill": "^0.1.3",
"react-dev-utils": "^6.1.1",
"resolve": "1.8.1",
+ "rust-native-wasm-loader": "^0.8.1",
"sass-loader": "7.1.0",
"style-loader": "0.23.0",
"terser-webpack-plugin": "1.1.0",
+ "toml-js": "0.0.8",
"url-loader": "1.1.1",
+ "wasm-loader": "^1.3.0",
"webpack": "4.19.1",
"webpack-dev-server": "3.1.9",
"webpack-manifest-plugin": "2.0.4",
diff --git a/packages/react-scripts/scripts/build.js b/packages/react-scripts/scripts/build.js
index 35cbfc15073..ceb4d106038 100644
--- a/packages/react-scripts/scripts/build.js
+++ b/packages/react-scripts/scripts/build.js
@@ -43,6 +43,7 @@ const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
const printHostingInstructions = require('react-dev-utils/printHostingInstructions');
const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
const printBuildError = require('react-dev-utils/printBuildError');
+const rustUtils = require('./utils/rustUtils');
const measureFileSizesBeforeBuild =
FileSizeReporter.measureFileSizesBeforeBuild;
@@ -82,6 +83,8 @@ checkBrowsers(paths.appPath, isInteractive)
fs.emptyDirSync(paths.appBuild);
// Merge with the public folder
copyPublicFolder();
+ // compile Rust to wasm
+ rustUtils.build();
// Start the webpack build
return build(previousFileSizes);
})
diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js
index 771f6dbf490..293d157480d 100644
--- a/packages/react-scripts/scripts/init.js
+++ b/packages/react-scripts/scripts/init.js
@@ -204,6 +204,22 @@ module.exports = function(
console.log('Initialized a git repository.');
}
+ const rustUtils = require('./utils/rustUtils');
+
+ if (rustUtils.isRustInstalled()) {
+ console.log('rust installed 👍');
+ } else {
+ console.log(
+ chalk.bold.red('rust not installed')
+ );
+ console.log(
+ 'install rust from here https://www.rust-lang.org/en-US/install.html'
+ );
+ return;
+ }
+
+ rustUtils.installRustWebAssemblyTools();
+
// Display the most elegant way to cd.
// This needs to handle an undefined originalDirectory for
// backward compatibility with old global-cli's.
diff --git a/packages/react-scripts/scripts/utils/rustUtils.js b/packages/react-scripts/scripts/utils/rustUtils.js
new file mode 100644
index 00000000000..046443cccd1
--- /dev/null
+++ b/packages/react-scripts/scripts/utils/rustUtils.js
@@ -0,0 +1,45 @@
+const execSync = require('child_process').execSync;
+const chalk = require('chalk');
+const commandExistsSync = require('command-exists').sync;
+const fs = require('fs');
+const toml = require('toml-js');
+
+module.exports = {
+ build: () => {
+ try {
+ // first build app.wasm and then optimize with wasm-gc
+ execSync(
+ 'rustc +nightly --target wasm32-unknown-unknown -O --crate-type=cdylib src/App.rs -o build/app.wasm && wasm-gc build/app.wasm',
+ { stdio: 'inherit' }
+ );
+ } catch (error) {
+ console.log(chalk.bold.red('error compiling rust'));
+ }
+ },
+ isRustInstalled: () => commandExistsSync('rustup'),
+ installRustWebAssemblyTools: () => {
+ if (!commandExistsSync('wasm-gc')) {
+ try {
+ execSync('cargo install wasm-gc', { stdio: 'inherit' });
+ } catch (e) {
+ console.log(e);
+ console.log(`${chalk.bold.red('error installing wasm-gc')} please install manually ${chalk.red('cargo install wasm-gc')}')`);
+ }
+ }
+ execSync(
+ 'cargo init --lib',
+ { stdio: 'inherit' }
+ );
+ fs.readFile('Cargo.toml', function (err, data) {
+ var cargo = toml.parse(data);
+ cargo.lib = {};
+ cargo.lib['crate-type'] = ['cdylib'];
+ cargo.lib.path = 'src/App.rs';
+ fs.writeFile('Cargo.toml', toml.dump(cargo), err => console.log(err));
+ });
+ execSync(
+ 'rustup target add wasm32-unknown-unknown --toolchain nightly',
+ { stdio: 'inherit' }
+ );
+ },
+};
diff --git a/packages/react-scripts/template/gitignore b/packages/react-scripts/template/gitignore
index 4d29575de80..404580abbd1 100644
--- a/packages/react-scripts/template/gitignore
+++ b/packages/react-scripts/template/gitignore
@@ -21,3 +21,6 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
+
+/target
+**/*.rs.bk
diff --git a/packages/react-scripts/template/rust-toolchain b/packages/react-scripts/template/rust-toolchain
new file mode 100644
index 00000000000..07ade694b1a
--- /dev/null
+++ b/packages/react-scripts/template/rust-toolchain
@@ -0,0 +1 @@
+nightly
\ No newline at end of file
diff --git a/packages/react-scripts/template/src/App.js b/packages/react-scripts/template/src/App.js
index 7e261ca47e6..25c43654d1b 100644
--- a/packages/react-scripts/template/src/App.js
+++ b/packages/react-scripts/template/src/App.js
@@ -1,15 +1,24 @@
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
+import { loadWasm } from "./wasmLoader";
class App extends Component {
+ constructor() {
+ super();
+ loadWasm(result => {
+ const calculateFactorial = result.instance.exports['fact'];
+ const x = 5;
+ alert(`the factorial of ${ x } is ${ calculateFactorial(x) }`);
+ });
+ }
render() {
return (