connected-retail v1.0.34
Fusion Starter
Fusion Starter is a comprehensive starter project for rapid application development using React.
Demo
https://fusion-starter.firebaseapp.com
Quick Start
First time? Do the initial setup.
git clone git@ghe.coxautoinc.com:CoxAuto-UI/fusion.git your-project-name-here
cd your-project-name-here
npm run setup
npm start -s
The setup step will prompt you for basic information on your project and write the relevant information to package.json. npm start
will run the automated build process, lint, start up a webserver, and open the application in your default browser. After running the start command, your code is rebuilt every time you hit save. See the full list of commands.
Once you're comfortable with how the example app works, remove the example app: npm run remove-demo
and start coding!
Initial Setup
- Install Node.js and Git. The defaults are fine.
- Request @coxautokc npm access. Register on npmjs.com and email Cory House your npm username. After you've been added, you can continue with the steps below.
- Login and save your npm credentials
npm adduser --registry=https://registry.npmjs.org --scope=@coxautokc
. This will prompt you for your npm username and password and save them to .npmrc so you aren't prompted to log in again. - Configure Git On Windows? Disable line ending conversion in Git.
- Configure your Editor for React. Install the appropriate JSX plugin and install the editorconfig plugin for your editor.
Why Use this?
- One command to get started - Type
npm start
to start development in your default browser. - Rapid feedback - Each time you hit save, changes reload and linting and automated tests run.
- One command line to check - All feedback is displayed on a single command line.
- No more JavaScript fatigue - Uses the most popular and powerful libraries for working with React.
- Working example app - The included example app shows how this all works together.
- Automated production build - Type
npm run build
to minify and bundle your app for production.
Who is using Fusion?
These Cox Automotive projects use Fusion:
Project | Business Unit |
---|---|
Service Dashboard | VinSolutions |
Bookout | Vinsolutions |
Customer Record | VinSolutions |
Customer Attachments | VinSolutions |
DMS Push | VinSolutions |
Connection Score | VinSolutions |
Customer-Facing Desking | VinSolutions |
GM Customer | VinSolutions |
GM Repair Order History | VinSolutions |
Digital Showroom | F&I |
Know of other apps using Fusion? Open an issue on this repository and let us know! π
Contributing
This is an inner sourced project, so anyone is free to contribute a pull request. Want to contribute? See CONTRIBUTE.md.
Technologies
Fusion is an opinionated React framework.
- Utilizes Create React App behind the scenes, so check the extensive create react app docs for more info
- References many recommended open source projects
- References reusable React components built here at Cox Automotive
- References styles that implement Tracksuit design guidelines (Password: suit-up). Tracksuit code
- This project includes an example app that showcases how all this comes together
Core Technologies and Resources for Learning More
Tech | Description | Learn More | |
---|---|---|---|
React | Fast, composable client-side components | Thinking in React, Pluralsight Courses, Smart vs Dumb Components, Stateless Functional Components, Using React State Correctly, State shouldn't depend on other state, React Best Practices, React performance measurement, Integrate React with existing apps | |
React Router | A complete routing library for React. | ||
React-Bootstrap | Many Fusion-UI components use React-Bootstrap behind the scenes. | ||
Redux | Enforces unidirectional data flows and immutable stores. Useful on larger apps with complex data flows. Alternative to Facebook's Flux. | Tutorial Video, Pluralsight Course, Code-based tutorial, Working with data in Redux, The Tao of Redux | |
Babel | Compiles ES6 to ES5. Enjoy the new version of JavaScript today | ES6 REPL, ES6 vs ES5, ES6 Katas, Pluralsight course | |
Webpack | Bundles npm packages and our JS into a single file. Supports hot reloading. | Quick Webpack How-to Pluralsight Course | |
Jest | Automated testing | Pluralsight Course, Snapshot testing, Snapshot testing video | |
TrackJS | JavaScript error tracking. Reports available at TrackJS.com. Email cory.house@vinsolutions.com to request access. | Β | |
ESLint | Lint JS. Reports syntax and style issues. Using eslint-plugin-react for additional React specific linting rules. | ||
SASS | Compiled CSS styles with variables, functions, and more. | Pluralsight Course | |
PostCSS | A tool for transforming CSS with JavaScript. We're using stylelint to lint styles | ||
Editor Config | Enforce consistent editor settings (spaces vs tabs, etc). | IDE Plugins | |
npm Scripts | Glues all this together in a handy automated build. | Pluralsight course, Why not Gulp? |
UI Components
Fusion includes a library of reusable React components.
FAQ
What do the scripts in package.json do?
What command line should I use?
How do I keep my app updated with the latest version of Fusion?
Can you explain the folder structure of the fusion-starter demo app?
Where are the files being served from when I run npm start
?
How is Sass being transpiled into CSS and landing in the browser?
I just want an empty starter kit.
Why are test files placed alongside the file under test (instead of centralized)?
How do I kill the process on the command line?
How do I proxy API Requests in Development?
How do I enable CORS on IIS-based Web APIs?
My editor marks my files as edited when I open them!
What do the scripts in package.json do?
Unfortunately, scripts in package.json can't be commented inline because the JSON spec doesn't support comments, so I'm providing info on what each script in package.json does here.
Script | Description |
---|---|
remove-demo | Removes the demo application so you can begin development. |
start | Starts dev webserver, opens the app in your default browser, and lints your code. |
build | Generates a minified build for production and writes it to /build. |
test | Runs tests (files ending in .spec.js or .test.js) using Jest and outputs results to the command line. Watches all files so tests are re-run upon save. |
coverage | Generates a code coverage report |
analyze | Generates an interactive analysis of what's in the production bundle using webpack-bundle-analyzer. This is useful for reducing your bundle size by finding what it's in your bundle. |
What command line should I use?
Whatever you like. This kit works on Windows, Mac, and Linux.
How do I keep my app updated with the latest version of Fusion?
Fusion-starter references the Fusion npm package. This package references all other Fusion npm packages inside for convenience. Type npm update
to get the latest updates. Here's the list of releases.
Can you explain the folder structure of the fusion-starter demo app?
Note that the files that start with a dot below will be hidden by default in Windows. Here's how to see them. Or type ls -la
in Git Bash.
.
βββ .editorconfig # Configures editor rules
βββ .gitignore # Tells git which files to ignore
βββ .npmrc # Configures npm to save exact by default
βββ README.md # Project documentation
βββ build # Folder where the final, production ready compiled version of your app is written (deploy this to production)
βββ package.json # Contains package configuration including a list of 3rd party libraries and utilities and npm scripts
βββ public # Folder where you will store images, documents, or other other files. Automatically copied to build directory.
βΒ Β βββ index.html # Start page
βββ yarn.lock # Yarn is an alternative to npm that installs faster and deterministically. This is the config file for Yarn. It's updated each time you run "yarn", which is equivalent to npm install.
βββ src # The app's source code
βΒ Β βββ actions # List of distinct actions (called Redux actions) that can occur in the app
βΒ Β βββ api # Centralized place to make AJAX calls
βΒ Β βββ components # React components
βΒ Β βββ index.js # Entry point for your app
βΒ Β βββ reducers # Redux reducers. Your state is altered here based on actions
βΒ Β βββ store # Redux store configuration
βΒ Β βββ styles # CSS Styles, typically written in Sass
βΒ Β βββ utils # Plain old JavaScript (POJOs). Pure logic. No framework specific code here. Think "business layer".
Where are the files being served from when I run npm start
?
Webpack serves your app in memory when you run npm start
. No physical files are written. However, the web root is /src, so you can reference files under /src in index.html. When the app is built using npm run build
, physical files are written to /build.
How is Sass being transpiled into CSS and landing in the browser?
It is handled differently in dev (npm start
) vs prod (npm run build
)
When you run npm start
:
- Sass-loader within Webpack uses node-sass to transpile *.scss files CSS.
- PostCSS applies Autoprefixer to apply any browser vendor prefixes to the CSS files.
- Webpack bundles the compiled CSS into bundle.js.
- bundle.js contains code that loads styles into the <head> of index.html via JavaScript. This is why you don't see a stylesheet reference in index.html. In fact, if you disable JavaScript in your browser, you'll see the styles don't load either.
The approach above supports hot reloading, which is great for development. However, it also create a flash of unstyled content on load because you have to wait for the JavaScript to parse and load styles before they're applied. So for the production build, we use a different approach:
When you run npm run build
:
- Same steps 1 & 2 above as with
npm start
. - The extract-text-webpack-plugin extracts the compiled CSS into styles.css.
- buildHtml.js adds a reference to the stylesheet to the head of index.html.
For both of the above methods, a separate sourcemap is generated for debugging in compatible browsers.
I just want an empty starter kit.
This starter kit includes an example app so you can see how everything hangs together on a real app. When you're done reviewing it, run this to remove the demo app:
npm run remove-demo
Don't want to use Redux? See the next question for some steps on removing Redux.
Do I have to use Redux?
Nope. Redux is useful for applications with more complex data flows. If your app is simple, Redux is overkill. Remove Redux like this:
- Run
npm run remove-demo
- Create a new empty component in /components.
- Open src/index.js and call render on the new top level component you created in step 2.
How do I remove React Router?
- Delete the following files:
src/routes.js
- Remove
import { Link, IndexLink } from 'react-router';
from top ofsrc/components/App.js
, add a reference tosrc/components/FuelSavingsForm.js
, and replace body of (implicit) render with this:<FuelSavingsPage />
.
How do I deploy this?
Type npm run build
. This will setup the project for production. It does the following:
- Minifies all JS.
- Sets NODE_ENV to prod so that React is built in production mode.
- Places the resulting built project files into /build. (This is the folder you'll deploy and expose to the world).
- Files in /public are copied to /build automatically. This is a great spot to place index.html, images, etc.
- Note that by default, Fusion produces a build assuming your app is hosted at the server root. To override this, specify the homepage in your package.json, for example:
"homepage": "http://mywebsite.com/relativepath",
Fusion will use this setting to set the proper root path in the generated HTML file.
Why are test files placed alongside the file under test (instead of centralized)?
Streamlined automated testing is a core feature of this starter kit. All tests are placed in files that end in .spec.js. Spec files are placed in the same directory as the file under test. Why?
- The existence of tests is highly visible. If a corresponding .spec file hasn't been created, it's obvious.
- Easy to open since they're in the same folder as the file being tested.
- Easy to create new test files when creating new source files.
- Short import paths are easy to type and less brittle.
- As files are moved, it's easy to move tests alongside.
How do I debug?
Since browsers don't currently support all of ES6, Fusion uses Babel to compile ES6 down to ES5. This means the code that runs in the browser looks different than what we wrote. But good news, a sourcemap is generated to enable easy debugging. This means your original JS source will be displayed in your browser's dev console. π
Note: When you run npm start
, no JS is minified. Why? Because minifying slows the build. So JS is only minified when you run the npm run build
script. See more on building for production below.
Also note that no actual physical files are written to the filesystem during the dev build. For performance, all files exist in memory when served from the webpack server.. Physical files are only written when you run npm run build
.
Tips for debugging via sourcemaps:
- Browsers vary in the way they allow you to view the original source. Chrome automatically shows the original source if a sourcemap is available. Safari, in contrast, will display the minified source and you'll have to cmd+click on a given line to be taken to the original source.
- Do not enable serving files from your filesystem in Chrome dev tools. If you do, Chrome (and perhaps other browsers) may not show you the latest version of your code after you make a source code change. Instead you must close the source view tab you were using and reopen it to see the updated source code. It appears Chrome clings to the old sourcemap until you close and reopen the source view tab. To clarify, you don't have to close the actual tab that is displaying the app, just the tab in the console that's displaying the source file that you just changed.
- If the latest source isn't displaying the console, force a refresh. Sometimes Chrome seems to hold onto a previous version of the sourcemap which will cause you to see stale code.
How do I handle images?
Via Webpack's file loader. Example:
<img src={require('./assets/images/myImage.jpg')} />
Webpack will then intelligently handle your image for you. For the production build, it will copy the physical file to /build and insert the appropriate path in your image tag.
How do I kill the process on the command line?
Hit Ctrl+C. Or, if you're in Webstorm, click the red X next to the terminal and then hit Alt+F12 to reopen the terminal.
How do I proxy API Requests in Development?
People often serve the front-end React app from the same host and port as their backend implementation. For example, a production setup might look like this after the app is deployed:
/ - static server returns index.html with React app
/todos - static server returns index.html with React app
/api/todos - server handles any /api/* requests using the backend implementation
Such setup is not required. However, if you do have a setup like this, it is convenient to write requests like fetch('/api/todos')
without worrying about redirecting them to another host or port during development.
To tell the development server to proxy any unknown requests to your API server in development, add a proxy
field to your package.json
, for example:
"proxy": "http://localhost:4000",
This way, when you fetch('/api/todos')
in development, the development server will recognize that itβs not a static asset, and will proxy your request to http://localhost:4000/api/todos
as a fallback. The development server will only attempt to send requests without a text/html
accept header to the proxy.
Conveniently, this avoids CORS issues and error messages like this in development:
Fetch API cannot load http://localhost:4000/api/todos. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Keep in mind that proxy
only has effect in development (with npm start
), and it is up to you to ensure that URLs like /api/todos
point to the right thing in production. You donβt have to use the /api
prefix. Any unrecognized request without a text/html
accept header will be redirected to the specified proxy
.
Currently the proxy
option only handles HTTP requests, and it wonβt proxy WebSocket connections.
If the proxy
option is not flexible enough for you, alternatively you can:
- Enable CORS on your server. See below for how to do it if your API is hosted in IIS.
- Use environment variables to inject the right server host and port into your app. Since fusion-starter uses create-react-app behind the scenes, reference this section in the create-react-app docs for information on configuring environment variables
How do I enable CORS on IIS-based Web APIs?
Fusion uses a Node webserver for serving the app on your local machine. This means you need to enable either: 1. Enable a proxy (see above)
or
- Enable Cross-origin Resource Sharing (CORS) on any existing IIS hosted APIs so that you can call them from this kit's dev web server.
Here's how to enable CORS:
Create an appSetting called "EnableCors" that is set to "true" for Local and Dev but "false" for all other environments.
<?xml version="1.0" encoding="utf-8"?>
<appSettings>
<!--Other app settings...-->
<add key="EnableCors" value="true" />
</appSettings>
You can create a convenience class to reference it:
public static class ConfigurationSettings
{
public static bool EnableCors = bool.TrueString.Equals(ConfigurationManager.AppSettings["EnableCors"], StringComparison.OrdinalIgnoreCase);
}
Then add this to your API's Global.asax:
protected void Application_BeginRequest(object sender, EventArgs e)
{
if (ConfigurationSettings.EnableCors)
{
EnableCrossOriginRequests(HttpContext.Current.Request);
}
}
/// <summary>
/// Enables cross-origin requests.
/// </summary>
/// <param name="request">The HTTP request</param>
private void EnableCrossOriginRequests(HttpRequest request)
{
var origin = request.Headers.Get("Origin");
// Can't set Access-Control-Allow-Origin header without the origin so just return.
if (origin == null) return;
var response = HttpContext.Current.Response;
response.AddHeader("Access-Control-Allow-Origin", origin);
response.AddHeader("Access-Control-Allow-Credentials", "true");
if (request.HttpMethod == "OPTIONS")
{
response.AddHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE");
// Allow all headers that are requested so that you can use custom headers.
var requestedHeaders = request.Headers.Get("Access-Control-Request-Headers");
if (requestedHeaders != null)
{
response.AddHeader("Access-Control-Allow-Headers", requestedHeaders);
}
response.AddHeader("Access-Control-Max-Age", "1728000");
response.End();
}
}
The example project includes /api/api.js. This file uses Axios to make AJAX calls. It's recommended to centralize your API calls there. See the example in api.js. api.js properly sets the base url based on whether it's running locally, but be sure to add a hosts entry for vinconnect.com (as outlined in the initial machine setup) to assure it works properly.
How does the mock API work?
Here's a blog post that summarizes our mock API set up.
Here's how to get rolling:
1. Create a schema using the JSON Schema Faker format. Save the schema in /src/api/mockDataSchema.js.
2. Fusion will look for the mockDataSchema.js file in src/api. If it finds it, it will generate a mock API using json-server when you run npm start
.
3. The mock API will be spun up on localhost:3002, so set the baseUrl in your API calls (located in api.js) accordingly.
An example mockDataSchema.js is included in Fusion-starter. So after running npm start
, you can hit the mock api endpoint and see one of the mocks generated by loading localhost:3002/customer in your browser. Every top level object you define in mockDataSchema.js will become its own endpoint and be exposed at localhost:3002/objectName.
My editor marks my files as edited when I open them!
This is the intended behavior of the EditorConfig VS Code plugin when end_of_line is set to lf
(as it is in Fusion) and the file is opened in a Windows OS. To fix this behavior in an existing Git repository, run the following commands (warning: this will discard all current changes and revert to the last commit):
git config core.autocrlf false
git rm --cached -r .
git reset --hard
The above commands prevent Git from converting the line endings to the Windows CR/LF on checkout so that EditorConfig's expectation of Unix line endings is met. More info here.
6 years ago