Giter Site home page Giter Site logo

wellyshen / react-cool-starter Goto Github PK

View Code? Open in Web Editor NEW
1.3K 50.0 243.0 14.39 MB

😎 🐣 A starter boilerplate for a universal web app with the best development experience and a focus on performance and best practices.

License: MIT License

JavaScript 6.53% TypeScript 91.20% SCSS 2.02% Shell 0.25%
redux express css-modules react-router webpack react redux-toolkit unit-testing boilerplate typescript

react-cool-starter's Introduction

REACT COOL STARTER

A simple but feature rich starter boilerplate for creating your own universal app. It built on the top of React, Redux, React Router and Express. Includes all the hot stuff and modern web development tools such as Redux Toolkit, TypeScript, Webpack, Babel, PostCSS, React Refresh, Jest and React Testing Library. See the β€œFeatures” section for other awesome features you can expect.

I will maintain the starter boilerplate and keep all of the technologies on trend. Welcome to join me if you want. Hope you guys love it 🀩

build status coverage status dependencies status devDependencies status code style: prettier All Contributors PRs welcome Twitter URL

Real Case Study

πŸ’‘ If you have built a production web app based on this starter, please open a PR to add it here.

  • Spinny is a fully inspected highest quality second hand cars with money-back guarantee. simple and transparent buying.
  • BAM Music is a new generation of music platform for audio visual professionals, filmmakers and content producers. Upgrade your soundtrack with great music that emphasizes your story!
  • Rendah Mag is a music magazine which exists to bring exposure to an ever-growing community, focusing on the latest Halftime, Beats & Experimental news & releases. Congrats for the amazing product.
  • DealDrop is the best place to find verified coupon codes, deals, promos and offers for thousands of stores & brands you love. Never pay full price again.
  • BECK Friends is an international delivery service, which is built based on this starter boilerplate. Congrats for successful migrating to React.

Features

Really cool starter boilerplate with the most popular technologies:

Who's the Starter for?

They're several React frameworks today, however this is a DIY oriented start-kit. It shows you how to build a universal web app from scratch and how to test it. If you're new to React or you want a ready-to-go solution, I'd recommend the following alternatives for you:

Requirements

Looking for Docker Image?

You can find Docker support version on this branch.

Getting Started

1. You can start by cloning the repository on your local machine by running:

git clone https://github.com/wellyshen/react-cool-starter.git
cd react-cool-starter

2. Install all of the dependencies:

yarn

3. Start to run it:

yarn build  # Building bundle
yarn start  # Running production server

Now the app should be running at http://localhost:8080

Note: You can change the port that you want from the ./src/config.

Script Commands

I use cross-env to set and use environment variables across platforms. All of the scripts are listed as following:

yarn <script> Description
dev Runs your app on the development server at localhost:3000. HMR will be enabled.
dev:build Bundles server-side files in development mode and put it to the ./public/server.
start Runs your app on the production server only at localhost:8080.
build Bundles both server-side and client-side files.
build:server Bundles server-side files in production mode and put it to the ./public/server.
build:client Bundles client-side files in production mode and put it to the ./public/assets.
analyze:server Visualizes the bundle content of server-side.
analyze:client Visualizes the bundle content of client-side.
lint Lints all .tsx?, .jsx? and .scss files.
lint:code Lints all .tsx? and .jsx? files (With --fix to auto fix eslint errors).
lint:type Runs type checking for .tsx? files.
lint:style Lints all .scss files (With --fix to auto fix stylelint errors).
lint:format Formats all files except the file list of .prettierignore.
test Runs testing.
test:watch Runs an interactive test watcher.
test:cov Runs testing with code coverage reports.
test:update Updates jest snapshot.

App Structure

Here is the structure of the app, which serves as generally accepted guidelines and patterns for building scalable apps.

.
β”œβ”€β”€ public                        # Express server static path and Webpack bundles output
β”‚   β”œβ”€β”€ favicon.ico               # App favicon
β”‚   β”œβ”€β”€ logo192.png               # App logo small
β”‚   β”œβ”€β”€ logo512.png               # App logo large
β”‚   └── manifest.json             # App favicon and logo manifest
β”œβ”€β”€ src                           # App source code
β”‚   β”œβ”€β”€ config                    # App configuration by environments
β”‚   β”‚   β”œβ”€β”€ default.ts            # Default settings
β”‚   β”‚   β”œβ”€β”€ index.ts              # Configuration entry point
β”‚   β”‚   └── prod.ts               # Production settings (overrides the default)
β”‚   β”œβ”€β”€ components                # Reusable components
β”‚   β”œβ”€β”€ pages                     # Page components
β”‚   β”œβ”€β”€ app                       # App root component
β”‚   β”œβ”€β”€ store                     # Redux store creator, actions + reducers (a.k.a slice)
β”‚   β”œβ”€β”€ services                  # API calls
β”‚   β”œβ”€β”€ utils                     # App-wide utils (e.g. mock store creator for testing etc.)
β”‚   β”œβ”€β”€ static                    # Static assets (e.g. images, fonts etc.)
β”‚   β”œβ”€β”€ theme                     # App-wide style and vendor CSS framework
β”‚   β”œβ”€β”€ types                     # App-wide type definitions
β”‚   β”œβ”€β”€ client                    # App bootstrap and rendering (Webpack entry)
β”‚   β”œβ”€β”€ routes                    # Routes configuration for both client-side and server-side
β”‚   └── server                    # Express server (with Webpack dev and hot middlewares)
β”œβ”€β”€ webpack                       # Webpack configurations
β”œβ”€β”€ jest                          # Jest configurations
β”œβ”€β”€ babel.config.js               # Babel configuration
β”œβ”€β”€ tsconfig.json                 # TypeScript configuration
β”œβ”€β”€ postcss.config.js             # PostCSS configuration
β”œβ”€β”€ .eslintrc.js                  # ESLint configuration
β”œβ”€β”€ .stylelintrc.js               # stylelint configuration
└── nodemon.json                  # nodemon configuration

Server-Side Security and Performance

Concerning the security and performance of Express in production, I already setup some middleware for you:

  • helmet - Helps secure Express server with various HTTP headers.
  • hpp - Express middleware to protect against HTTP Parameter Pollution attacks.
  • compression - Gzip compression support for speeding up Express server responses.

Note: It's just a basic protected mechanism for your app, you can see the security best practices for more advanced configuration.

Develop with Redux Toolkit

Redux Toolkit is the official, opinionated, batteries-included toolset for efficient Redux development. It includes several utility functions that simplify the most common Redux use cases. In a word, we can do more work with less code, start from the tutorial to learn more about it.

Let's see how powerful it is by a simple asynchronous data fetching example:

import { createSlice } from "@reduxjs/toolkit";
import axios from "axios";

const initialState = {
  readyStatus: "invalid",
  items: [],
  error: null,
};

const userList = createSlice({
  // A name for action types
  name: "userList",
  initialState,
  // An object of "case reducers", key names will be used to generate actions
  reducers: {
    getRequesting: (state) => {
      // Write an immutable updated state by a mutable way, thanks to the built-in Immer middleware
      state.readyStatus = "request";
    },
    getSuccess: (state, { payload }) => {
      state.readyStatus = "success";
      state.items = payload;
    },
    getFailure: (state, { payload }) => {
      state.readyStatus = "failure";
      state.error = payload;
    },
  },
});

// We can get the "reducer" and "actions" from the slice instance
export default userList.reducer;
const { getRequesting, getSuccess, getFailure } = userList.actions;

export const fetchUserList = () => async (dispatch) => {
  dispatch(getRequesting());

  try {
    const { data } = await axios("/api/users");

    // Dispatch the action once data is ready via the built-in Redux Thunk middleware
    dispatch(getSuccess(data));
  } catch (error) {
    dispatch(getFailure(error.message));
  }
};

Overview

Functional Components and Hooks

React v16.8 introduced a series of Hooks, which let you use state and other React features without writing a class. In the starter boilerplate, you can see how I leverage the benefit of functional components + hook APIs to write a demo with clean code.

Adding Routes

This starter use React Router library to manage our routes. For the purpose of SSR with data pre-fetched, I put the routes in a centralized Route Config. You can setup your routes in the ./src/routes/index.ts. For example:

import PageComponent from "../pages/PageComponent";

export default [
  {
    // Define your route path
    path: "/top-path",
    // If the route matches the location.pathname exactly or not (used for index route usually)
    exact: true,
    // Add your page component here
    component: PageComponent,
    // Add your sub route component here
    routes: [
      {
        path: "/top-path/sub-path",
        component: SubComponent,
      },
    ],
  },
  // Other routes...
];

Data Fetching from Server-side

Strongly recommend to write Redux actions and reducers via the createSlice API of Redux Toolkit (start from the tutorial if you are new). The starter using axios as the data fetcher, it's quite simple and easy to use. If the action is asynchronous then it will return a Promise (or a Promise.all) in the inner function.

Register the action(s) in the ./src/routes/index.ts, which have to be called from server-side:

export default [
  {
    path: "/top-path",
    exact: true,
    component: PageComponent,
    // Async actions in the loadData function will be fetched from server-side
    // You can access the URL parameters, Redux store, HTTP request and response by the event object
    loadData: ({ params, getState, req, res }) => [
      myReduxAction(),
      // More pre-fetched actions...
    ],
  },
];

The action(s) will be dispatched through the ./src/server/ssr.tsx on server-side:

app.get("*", (req, res) => {
  // ...

  // Here's the method for loading data from server-side
  const loadBranchData = () => {
    const branch = matchRoutes(routes, req.path);

    const promises = branch.map(({ route, match }) => {
      if (route.loadData) {
        return Promise.all(
          route
            .loadData({
              params: match.params,
              getState: store.getState,
              req,
              res,
            })
            .map((item) => store.dispatch(item))
        );
      }

      return Promise.resolve(null);
    });

    return Promise.all(promises);
  };

  // ...
});

In client-side, don't forget to invoke the action(s) in componentDidMount or useEffect hook. This ensures that if the component is reached on the client, then the same actions will be invoked. It's up to the action(s) to figure out if fetches for data need to be made or not:

// Use React class component
componentDidMount() {
  // Invoke your redux action(s) for client rendering
  this.props.myReduxAction();
}

// Use functional component
useEffect(() => {
  myReduxAction();
}, [])

For better architecture, we can centralize the data fetching methods in one place like how I did in the Home page.

const SomePage = () => {
  // ...

  // Fetch client-side data here
  useEffect(() => {
    dispatch(fetchUserListIfNeed());
  }, [dispatch]);

  // ...
};

// Fetch server-side data here, the method will be used by the route config
export const loadData = () => [fetchUserListIfNeed()];
export default SomePage;

Code Splitting

One great feature of the web is that you don’t have to make your visitors download the entire app before they can use it. You can think of code splitting as incrementally downloading the app. It divides your code into small pieces called "chunks" to reduce the size of bundle loaded by user. Reducing the size of a chunk makes it load and run faster.

To accomplish this, I integrate loadable-components into this starter. The reason I choose the library is because of its design philosophy of SSR. It works seamless with the starter rather than others. Let’s see how we split our app by page:

I use the following folder/file structure:

 └─ pages
    └─ SomePage
       |- PageComponent.tsx  // The page component
       └─ index.tsx          // Wrap the component into async component

The index.tsx will be:

import loadable from "@loadable/component";

import { Error, Loading } from "../../components";
import { loadData } from "./PageComponent";

// Dynamically import your page component
const AsyncPage = loadable(() => import("./PageComponent"), {
  //  <Loading /> will be displayed when the component is being loaded
  fallback: <Loading />,
});

export default (props) => (
  // Wrap an <ErrorBoundary /> to catch the error of <AsyncPage /> (via "componentDidCatch()" life cycle)
  <ErrorBoundary>
    <AsyncPage {...props} />
  </ErrorBoundary>
);
export { loadData }; // Export SSR data fetching method as well

Then you can setup the route as usual.

Note: I just show a general case page-based splitting, however you can even split your app by component-based depends on your needs. For more advanced configuration, please refer to the document. In additional, loadable-components supports Webpack pre-fetching/pre-loading out of the box. <link rel="preload"> and <link rel="prefetch"> can be added directly server-side to improve performances.

Managing Title, Meta, Styles and Scripts

The ./src/app/index.tsx (app root component) defines the base title and meta in a <Helmet {...config.APP} /> component. Any sub-component can override/add properties (supports meta, link, script, style tags and html attributes). See the react-helmet document for more info.

App Configuration

You can store app settings under the ./src/config. By default the default.ts will be loaded. If the process.env.NODE_ENV matches to production (alias as !__DEV__), the prod.ts will be used instead, and it inherits the properties of default.ts.

You can access the correct configuration with:

import config from "./config";

Styles

The starter supports CSS, SASS and CSS modules is auto enabled for all files the [name].module.* naming convention. I use PostCSS plugin to parse CSS and add autoprefixer to your stylesheet. You can access your stylesheet with two ways.

With CSS modules:

import styles from "./styles.module.scss";

// ...

return (
  <div className={styles.myClass}>
    {/* The className matches one of CSS classes in your .scss file */}
    <Helmet title="My title" />
    {this.renderContent()}
  </div>
);

Without CSS modules:

import "./styles.scss";

// ...

return (
  <div className="myClass">
    {/* Use the CSS class as normal */}
    <Helmet title="My title" />
    {this.renderContent()}
  </div>
);

By the way, if you want to use vendor CSS frameworks or global styles, just import it through the ./src/app/index.tsx file (app root component). For example:

import "../../theme/normalize.css"; // Import the vendor stylesheet first
import styles from "./styles.scss"; // Then your based stylesheet

const App = ({ route }) => (
  // ...
};

Image and Font

It's super easy to render the image and font both on client and server, the usage would be like below.

Using image:

import logo from "../static/logo.svg";

<img src={logo} alt="Logo" role="presentation" />;

Using font-awesome:

// With CSS modules
import styles from "./styles.scss";

// ...

return (
  <div>
    <div>
      <i className={styles.iconUser} /> Welly
    </div>
  </div>
);

// Without CSS modules
import "./font-awesome.css";

// ...

return (
  <div>
    <div>
      <i className="fa fa-icon" /> Welly
    </div>
  </div>
);

For using CSS modules, you have to set the proper font path in your scss/sass file:

$fa-font-path: "../node_modules/font-awesome/fonts";
@import "../node_modules/font-awesome/scss/font-awesome";

.icon-user {
  @extend .fa;
  @extend .fa-user;
}

Boost App Performance

In this starter, you can see I use React.PureComponent and React.memo to demonstrate the basic performance optimizing for React app. The two APIs are used in different ways.

  • React.PureComponent is used for React class components. It can do shallow prop and state comparison for a performance boost:
import { PureComponent } from "react";

class MyComponent extends PureComponent {
  // Only re-renders if props change
}
  • React.memo is used for functional components. It plays the same role as React.PureComponent:
import { memo } from "react";

const MyComponent = memo((props) => {
  // Only re-renders if props change
});
  • In addition, you can also use React hooks like useMemo or useCallback to avoid expensive calculations on every render:
import { useMemo, useCallback } from "react";

// Performance optimizing via useMemo()
const ParentComponent = (props) => (
  <div>
    {/* Only re-renders if "a" change */}
    {useMemo(
      () => (
        <ChildComponent someProp={a} />
      ),
      [a]
    )}
  </div>
);

// Performance optimizing via useCallback()
const ParentComponent = (props) => (
  <div>
    {/* Return a memorized callback that only changes if "a" changed */}
    {/* This is useful to prevent child component from unnecessary renders */}
    <ChildComponent
      callback={useCallback(() => {
        doSomething(a);
      }, [a])}
    />
  </div>
);

For more performance optimizing techniques. Please see the Optimizing Performance topic.

TypeScript

TypeScript is a typed super-set of JavaScript. It's getting more and more popular in the Front-end world. And being widely used by many libraries. If you are new to TypeScript, you can check out its document here.

TypeScript has been integrated with our application to bring the following benefits:

  • Type safety for components, reducers, state and actions.
  • Many IDEs support the hints of TypeScript, which give us a superior developer experience.
  • Easy refactoring of typed code.
  • In general, more types less bugs. Read this article to learn more.

Code and Style Lint

ESLint (with Airbnb configuration), typescript-eslint, stylelint, Prettier and lint-staged are integrated into this starter to maintain a consistent code style and give you a elegant code formatting. You can configure your lint rules through the .eslintrc.js, .stylelintrc.js, and prettier configuration file.

Unit Testing

This starter use Jest as the testing framework. We also use React Testing Library with jest-dom, give you a simple and complete React DOM testing utilities that encourage good testing practices.

Jest support the feature of snapshot testing, which is very powerful for testing React component. Give it a try, you'll be impressed. The unit testing focus on three parts as below:

  • Components
  • Actions
  • Reducers

By the way, Jest built-in code coverage reports, the report files are generated in the ./coverage folder. You can configure the ./jest/config.js to define which files that you want to cover. For example:

module.exports = {
  collectCoverageFrom: [
    "src/pages/**/*.tsx", // Define the files, which want to be covered
    "!src/pages/index.ts", // The files will be ignored by code coverage
  ],
  // Other configurations...
};

You can also use istanbul's ignore hints to specify specific lines of code in a JavaScript file to skip code coverage.

How to Deploy

To deploy you app to cloud service (e.g. AWS, GCP, Azure etc.), you can follow the instructions below.

  1. Build then install production dependencies:
yarn build                  # Building bundle
rm -rf node_modules         # After building remove node modules
yarn install --production   # Then install dependencies only
  1. Pack necessary folders/files to your Node.js server:
  • βœ… public
  • βœ… node_modules
  • βœ… package.json
  1. Run your app:
yarn start

Ideally, the above steps can be integrated into your CI. I recommend you to pack the yarn.lock file for yarn installation by CI.

Troubleshooting

  • If you encounter the markup mismatches error (it's a React universal issue, which usually occurs due to the non-synchronized rendering result between client and server), you can do:

    • Restart the server to solve it.
    • Or for v16.1.0 up, you can use suppressHydrationWarning attribute for intentional client/server text mismatches (#11126).
  • If you are on windows and encounter the following error: Expected linebreaks to be 'LF' but found 'CRLF' linebreak-style. The following rule must be added to .eslintrc.js.

// ...
"rules": {
  "linebreak-style": "off",
  // Other rules...
}

Contributors ✨

Thanks goes to these wonderful people (emoji key):


Welly

πŸ’» πŸ“– 🚧

Microflow

🌍

Jason Bacchetta

πŸ”§

Nikita Balabaev

πŸ’»

James Sherry

πŸš‡ πŸ›

Zack Pelz

🌍

apapacy

πŸ’»

martin2786

πŸ“–

iamacup

πŸ”§

Maxim

πŸ”§

Benny Neugebauer

🌍

A. S. Lapkov

πŸ’»

Alireza Valizade

πŸ’»

Grant Millar

πŸ› πŸ’»

Bart

πŸ›

Morteza Tourani

πŸ’»

Tom Kiernan

🌍

Nathan KREMER

πŸ’»

Amer Lotfi Orimi

πŸ”§ πŸ’»

Muhammad Umar

πŸ’»

Denny Vuong

πŸ“– πŸ’»

Matt Carlotta

πŸ’»

This project follows the all-contributors specification. Contributions of any kind welcome!

react-cool-starter's People

Contributors

alirezavalizade avatar allcontributors[bot] avatar amerllica avatar apapacy avatar aslapkov avatar bennycode avatar bjvda avatar dependabot-preview[bot] avatar dependabot[bot] avatar forwardomg avatar greenkeeper[bot] avatar iamacup avatar jabacchetta avatar jmsherry avatar martin2786 avatar mortezat avatar renovate-bot avatar rid avatar tomkiernan120 avatar w3debugger avatar wellykkstream avatar wellyshen avatar xd3coder avatar zace2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-cool-starter's Issues

Rendering routes error: TypeError: Converting circular structure to JSON

Sometime I have an error.

==> 😭 Rendering routes error: TypeError: Converting circular structure to JSON
GET / 404 1294.641 ms - 12

I don't know any relations and how to reproduce that error. Sometime I can start app and app works well and after I can restart server and have the error. Very strange. Because I didn't change any code. Run clear:all command doesn't help. But after reboot a server the app can works corrects.

2 warnings

Im getting 2 warnings when running the app.

Warning: Accessing PropTypes via the main React package is deprecated. Use the prop-types package from npm instead.

Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
(client) <div class="styles__App-2nmMK" d
(server) <div class="_2nmMK" data-reactro

SSR not working correctly

It doesn't do SSR for me. I have changed DISABLE_SSR global variable to false, but when I turn off JavaScript or open source code it doesn't show expected content.

Problem wit nodemon

I have a problem with nodemon. I think it's very important to use only webpack for rebuilding components and style for them. I decided to turn off stylelinter and take control of writing my styles by myself. Hovewer, when I wrote code like that :
@import '../../theme/variables' body { background-color: $color-dark-gray; font-family: 'Helvetica-Light', Helvetica, Arial, sans-serif; }, where it lacks semicolons after import of file, I got follow message in terminal:
[nodemon] app crashed - waiting for file changes before starting....
The only way to repair it - to execute "rs" for reload server but it's too long.
I suspect that it happens because of WebpackIsomorphicTools, maybe it'll be better to use a classic webpack way as mentioned here? Or don't use it in development mode.
Thanks.

Insert repeat styles and putting in new script to head on each hot reload

Hi, I have some problem with styles and hot reloading.

I use branch server_bundle

1. Styles

When I load my page, styles are put in tag <style>
screen
But in 3-5 seconds some links put in as well.
screen
What styles are it?

2. Hot reload

It appears new script on every hot reload.
screen
May you explain me how it works and can it impact on performance?

3. Bug CSS MODULES

I Have very strange bug with using css modules in production mode - the page without styles loads at first and then page with styles. There is blick between them.
Check it out, just run npm run production in server_bundle branch.
It happens only with CSS Modules mode.

I'll be really gratefull for any help. Thanks.

fsevents

I work for a large factory where I develop and maintain software that does measurements, analysis and produces reports about the process. Because it is used at different places I once decided to make a web application and use php/js/jquery as tools. It is running good but because of the size hard to maintain so I have started to look for a better solution.
I investigated Agular but didn't like it because of Google (the factory is in China and a lot of Google services are blocked), so I looked for another solution and thought Meteor with React might be a good start until I read about the deployment issues - it seems Meteor only wants to have it installed on their own servers..
React/Nodejs is in the end the way I want to give a try and hot loading would be nice to improve the development speed. So I stumbled upon react-cool-starter because I don't want to reinvent the wheel.

I started to install it but received the following message:

aevl@aevl-Lenovo:/react/react-cool-starter$ npm install
npm WARN optional Skipping failed optional dependency /chokidar/fsevents:
npm WARN notsup Not compatible with your operating system or architecture: [email protected]
npm WARN [email protected] requires a peer of eslint-plugin-import@^1.16.0 but none was installed.
npm WARN [email protected] requires a peer of eslint-plugin-import@^1.16.0 but none was installed.
aevl@aevl-Lenovo:
/react/react-cool-starter$

I could start the server without problems but I am not sure what to think about the warning, can you explain?

The os I run it on is Lubuntu 16.04.1 (Xenial)

Trouble deploying to Amazon Elastic Beanstalk

Firstly I would like to say thanks, I tried many boiler plates to find a good SSR react template and this is by far the best and I now have a fully working website.

I have hit issues trying to deploy to AWS, I have added a local variable for NODE_ENV = production and changed the EB start command to 'node ./index.js' then built the project and deployed to EB.

It fails with unable to find webpack-isomorphic-tools which is required in index.js but is in dev-dependencies in the package.json? I tried moving to dependencies but then just get 'waiting for the first webpack build to finish' continuously and a 502 error from the page?

Any idea what I am doing wrong, do I need to move any other packages up to dependencies for this to run in AWS, the 'yarn start:production' works fine on my local machine, but there I obviously have all of the packages anyway?

Again, thanks for a great boiler plate

Server for production

Thank you for your work. Do you have plans to get the server code transpiled for production? Right now it uses babel register instead of being run through Webpack or Babel

how to run in develop mode

i clone your repo,run npm install then run npm run start
webpack-isomorphic-tools shows (waiting for the first Webpack build to finish) infinitely
its because there is never a webpack-assets.json file on the root folder

so how to run in develop mode?

build error

I am trying to get a better grip on the package and tried to build it to see how the resulting code was.
The docs told me that after a 'npm build' the result should be in the public/dist folder. This folder contains several files but what I am missing is for instance a simple index.html (or htm/php) file. So how to I put it on the server?

Next I cleaned the dist folder and tried to build it again with npm install.
Now I ran into more serious problems, below is the content of npm-debug.log:

0 info it worked if it ends with ok
1 verbose cli [ '/usr/local/bin/node',
1 verbose cli '/usr/local/bin/npm',
1 verbose cli 'run',
1 verbose cli 'start:production' ]
2 info using [email protected]
3 info using [email protected]
4 verbose run-script [ 'prestart:production',
4 verbose run-script 'start:production',
4 verbose run-script 'poststart:production' ]
5 info lifecycle [email protected]prestart:production: [email protected]
6 silly lifecycle [email protected]
prestart:production: no script for prestart:production, continuing
7 info lifecycle [email protected]start:production: [email protected]
8 verbose lifecycle [email protected]
start:production: unsafe-perm in lifecycle true
9 verbose lifecycle [email protected]start:production: PATH: /usr/local/lib/node_modules/npm/bin/node-gyp-bin:/home/aevl/react/react-cool-starter/node_modules/.bin:/usr/local/bin:/home/aevl/bin:/home/aevl/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
10 verbose lifecycle [email protected]
start:production: CWD: /home/aevl/react/react-cool-starter
11 silly lifecycle [email protected]start:production: Args: [ '-c', 'npm run build && npm run start:prod' ]
12 silly lifecycle [email protected]
start:production: Returned: code: 1 signal: null
13 info lifecycle [email protected]~start:production: Failed to exec start:production script
14 verbose stack Error: [email protected] start:production: npm run build && npm run start:prod
14 verbose stack Exit status 1
14 verbose stack at EventEmitter. (/usr/local/lib/node_modules/npm/lib/utils/lifecycle.js:245:16)
14 verbose stack at emitTwo (events.js:106:13)
14 verbose stack at EventEmitter.emit (events.js:191:7)
14 verbose stack at ChildProcess. (/usr/local/lib/node_modules/npm/lib/utils/spawn.js:24:14)
14 verbose stack at emitTwo (events.js:106:13)
14 verbose stack at ChildProcess.emit (events.js:191:7)
14 verbose stack at maybeClose (internal/child_process.js:852:16)
14 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:215:5)
15 verbose pkgid [email protected]
16 verbose cwd /home/aevl/react/react-cool-starter
17 error Linux 4.4.0-43-generic
18 error argv "/usr/local/bin/node" "/usr/local/bin/npm" "run" "start:production"
19 error node v6.2.1
20 error npm v3.9.3
21 error code ELIFECYCLE
22 error [email protected] start:production: npm run build && npm run start:prod
22 error Exit status 1
23 error Failed at the [email protected] start:production script 'npm run build && npm run start:prod'.
23 error Make sure you have the latest version of node.js and npm installed.
23 error If you do, this is most likely a problem with the react-cool-starter package,
23 error not with npm itself.
23 error Tell the author that this fails on your system:
23 error npm run build && npm run start:prod
23 error You can get information on how to open an issue for this project with:
23 error npm bugs react-cool-starter
23 error Or if that isn't available, you can get their info via:
23 error npm owner ls react-cool-starter
23 error There is likely additional logging output above.
24 verbose exit [ 1, true ]

It's strange behavior of app

Hi, could you explane me, what the profit of using async reducers and async routes is?
When I run your app it's load data in first time, despite on the data have already been in app(isomorphic routing with "preload" data), then when I click one of links I see "...loading" again, when come back Home Page I see "...loading" again .
I thought It's too many useless requests to the API. Maybe I am wrong?
If you have time, write me an answer.
Also, I found small bug with stylelinter, when I make mistake in my scss file It shows message, but after repairing webpack doesn't hot reload. It is terminated via failOnErrors: false, but then webpack'll be compile css even with errors.
Thanks

Deployment on Heroku

Hey @wellyshen
First of all thanks for coming up with a great repository that works flawlessly.

I have been able to run in dev mode as well as build it on the localhost environment but the problem creeps in once I deploy it on Heroku. I am following the standard process as found in react-redux-universal

  1. Remove the "PORT": 8080 line from the betterScripts / start-prod section of package.json.
  2. heroku config:set NODE_ENV=production
  3. heroku config:set NODE_PATH=./src
  4. heroku config:set NPM_CONFIG_PRODUCTION=false

Also on pushing it on heroku master, the build log says "build succeeded" but on opening the link, it shows application error. Could you please tell what else needs to be done to make it work?

functions getting called on their own going in an infinite loop

Hey, It seems functions are getting called on their own "server-side" and keeps calling them forever:

For example I am using an onClick on a button to call a function login():

login = () => {
    console.log('should login');
  }

<button className="btn btn-primary" onClick={this.login()}>Sign in with google</button>

This console.log calls forever and goes into an infinite loop.
Please suggest what to do and I want to make certain functions purely client-side like login and registration etc.

Also wanted a little clarification on mapDispatchToProps if it is written in the standard way?

SSR render components without data

Hi! Thanks for the awesome starter.

When the server render the HTML server side, i didn't have the state:

const routerContext = {};
let htmlContent = renderToString(
	<Provider store={store}>
		<StaticRouter location={req.url} context={routerContext}>
			<App />
		</StaticRouter>
	</Provider>,
);

and i return the HTML with the initial state of all the containers. When the client try to render in the same div to reuse the generated HTML, React warn me that the generated HTML is different (i render with window.__INITIAL_STATE__).

Should i do render after loaded the data from the component load? If I do it, i do multiple render, because the first is needed for redirect:

// Check if the render result contains a redirect, if so we need to set
// the specific status and redirect header and end the response
if (routerContext.url) {
	ctx.status = 301;
	ctx.redirect(routerContext.url);
	ctx.body = '';
	return;
}

so i need to do it before the data is loaded.

Thanks in advance

index.html ?

I already have an api server and so would adapt your awesome project to it as a front end,
I'll just: yarn build:client

Q: Could you please create an index.html file?

Thanks mate from Sydney

When not using CSS modules, the nested modules' styles get overwritten

Is there a way to apply the App container's styles last, so as to give precedence to the nested components' styles? Currently this is not possible with the structure we have.

Steps to reproduce:

  1. In ./tools/webpack/config.js set CSSModules = false
  2. Add the following to ./src/containers/App/styles.scss
.test {
  color: red;
}
  1. Add the following to ./src/containers/Home/styles.scss
.test {
  color: blue;
}
  1. Add the following to ./src/containers/Home/index.js's render function
render() {
  ...
  <span className="test">This should be blue, but it's red.</span>
  ...
}

Error when running server.js

After successfull yarn install and yarn build, command node ./build/server.js return error:

C:\Users\n.balabaev\Source\Repos\react-cool-starter>node ./build/server.js
C:\Users\n.balabaev\Source\Repos\react-cool-starter\build\server.js:468
if (__DEV__) {
    ^

ReferenceError: __DEV__ is not defined
    at Object.<anonymous> (C:\Users\n.balabaev\Source\Repos\react-cool-starter\build\server.js:468:5)
    at __webpack_require__ (C:\Users\n.balabaev\Source\Repos\react-cool-starter\build\server.js:21:30)
    at Object.<anonymous> (C:\Users\n.balabaev\Source\Repos\react-cool-starter\build\server.js:1761:18)
    at __webpack_require__ (C:\Users\n.balabaev\Source\Repos\react-cool-starter\build\server.js:21:30)
    at C:\Users\n.balabaev\Source\Repos\react-cool-starter\build\server.js:67:18
    at Object.<anonymous> (C:\Users\n.balabaev\Source\Repos\react-cool-starter\build\server.js:70:10)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)

Hot reload

Hi,

Thank for your work, i have one problem's if it's one i'm not sure.

When i create new components, i create js and scss file hot reload relaunch the browser and he don't find the scss file.

I need to relaunch build cmd.

Thank you for help.

Accessing the store [Question]

I was trying to access the store that is passed down to html.js from the server.js. First I tried the same approach wih the Connector and passing down the reducer in the connect. But the value for my reducer is always undefined. Is the dispatch part required ? from what I understand I can send connect like this:

const mapStateToProps = ({ tracker }: Reducer) => ({ tracker });

const connector: Connector<{}, Props> = connect(mapStateToProps);

export default connector(FlowHome);

Reducer

/* @flow */

import _ from 'lodash';

import {
  TRACKER_NEXT_STEP,
} from './action';
import type { Tracker, Action } from '../../types';

type State = Tracker;

const initialState = {
  currentStep: '0',
  completedSteps: [],
};

export default (state: State = initialState, action: Action): State => {
  switch (action.type) {
    case TRACKER_NEXT_STEP:
      return _.assign({}, state, { currentStep: action.currentStep });
    default:
      return state;
  }
};

Type

export type Tracker = {
  currentStep: string,
  completedSteps: Array<string>,
}

export type Reducer = {
  tracker: Tracker,
  router: any,
};

export type Action = { type: 'TRACKER_NEXT_STEP', currentStep: string };

Any suggestion on what is the correct way to get the state this way. This reducer specifically is really simple and does not have any calls to the server. And the state holds a string.

Thanks

Problem dispatching actions from different components

First of all,
thankyou @wellyshen for the great boilerplate.

I have the following structure from a checkout of the boilerplate 5 days ago.

        /Tags/
             /index.js //component
             /reducer.js // the reducer for that component
             /actions.js // all the actions that can be performed by that component
       /Products/
             /index.js
             /reducer.js 
             /actions.js 

I'm trying to have a component connect to two reducers.

I use redux's connect and mapStateToProps in this way:

const mapStateToProps = state => (
    { products: state.get('products').products, tags: state.get('tags').tags }
  );
  
  export default connect(mapStateToProps)(Products);

Now, I'd like to dispatch from the very same component two actions.
One action is from the actions in the same component folder, and the other is from the folder in tags.
The name of the actions are unique.
The actions are executed correctly and both try to update their own reducers with dispatch().
The reducer of tags doesn't receive his own dispatch (it doesn't see it), while the reducer of Products, receives both.

I believe i'm doing a bit (lot) of confusion with the function dispatch that seams to be the same and coming from the component itself.
Actions that are dispatched from the Tags component are processed correctly by its reducer.

Any suggestion?

using css with this starter

Hey,
I saw the part in readme where it explains how to use css with the boilerplate.

Somehow in my case it is not importing the css modules.

What I am doing is, let's say we have a div which needs to be given some styling
In App,js
<div className="left-half"> <h1 className="o-header__title titledesk">Something</h1> </div>

and in normalize.css

.left-half{ color: red; width: 100%; height: 800px; background-color: #2bb1de; }

Should it be written in some other way?

React router v4

Hi @wellyshen:)
Do you have a plan to add react router v4 to your boilerplate?
It's really great solution for routing, but it has some disadvantages like unclear way for server side routing and async routes and reducers as well.
Thanks

IE 11 promise

App does not work properly in IE 11. I suggest adding babel-polyfill. Something like below should fix the problem:

  1. npm install --save babel-polyfill
  2. Add 'babel-polyfill' in vendor array.

Add bootstrap css

Hi,

First of all thanks for a great starter. I was having some problems trying to add bootstrap to the starter. I tried several ways .

  1. Require the bootstrap.css at Html.js
  2. Import the style , in general styles import section at App/index.js
  3. Tried adding react-bootstrap(Compos work , but still import still fails )

The above methods always throw me an error with the fonts loader: woff -woff2-eot-svg etc. It saids it can not find the "file-loader". Given this I tried playing with the loaders order but still didnt work.

Any idea to get this working, thanks

Multiple Entries with Different Styles

I am wanting to integrate some of the code that you have created here into my own stack to achieve a better development experience but I am running into a snag.

Your application assumes one entry, while mine has several. The reason for this is that we have different applications for different types of users (admin vs. customer etc.).

I know how to set up multiple entries with Javascript and that has gone well, but I can't figure out how to handle the SCSS files? In renderHtmlPage, it seems you loop over all compiled style assets and inject them in. In my use case, we wouldn't want the styles of other apps bleeding into eachother.

My webpack setup before was able to determine what CSS we brought in based on the entry but it seems that is not the case anymore. WIT is compiling all of them. So if I could get some advice or help on how to set up multiple 'views' or entries and have the style assets be dynamic based on the entry, that would be greatly appreciated!

P.S. I love the starter-kit!

server is bundle into a single file in production mode

I am really confusing how to build server side node code for production,you are using webpack and bundle it all with a single server.js file which contains some react component code...

if it's true not to bundle server code... if we should just use babel to compile our node code and compoinent code to es5 for production?

Examples using react-bootstrap

Does anyone have a sample of adding a nav bar to this starter using react-bootstrap?

I"ve crated a component at src/compontents/NavBar/index.js

import React from 'react';
import { Nav, Navbar, NavItem, NavDropdown, MenuItem } from 'react-bootstrap';


const NavBar = (
  <Navbar inverse collapseOnSelect>
    <Navbar.Header>
      <Navbar.Brand>
        <a href="https://github.com/kecorbin/react-collins-ui">React-Bootstrap</a>
      </Navbar.Brand>
      <Navbar.Toggle />
    </Navbar.Header>
    <Navbar.Collapse>
      <Nav>
        <NavItem eventKey={1} href="/jobs">Jobs</NavItem>
        <NavItem eventKey={2} href="/">Users</NavItem>
        <NavDropdown eventKey={3} title="Dropdown" id="basic-nav-dropdown">
          <MenuItem eventKey={3.1}>Action</MenuItem>
          <MenuItem eventKey={3.2}>Another action</MenuItem>
          <MenuItem eventKey={3.3}>Something else here</MenuItem>
          <MenuItem divider />
          <MenuItem eventKey={3.3}>Separated link</MenuItem>
        </NavDropdown>
      </Nav>
      <Nav pullRight>
        <NavItem eventKey={1} href="#">Link Right</NavItem>
        <NavItem eventKey={2} href="#">Link Right</NavItem>
      </Nav>
    </Navbar.Collapse>
  </Navbar>
);

export default NavBar;

This code is based upon the samples at https://react-bootstrap.github.io/components.html#navbars

What I cannot figure out is where I should place the line
ReactDOM.render(navbarInstance, mountNode);

I've tried a few different places, but usually end up with the following error message:

Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.
    in Unknown
    in Router (created by StaticRouter)
    in StaticRouter
    in Provider
==> 😭  Rendering routes error: Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. Check the render method of `StatelessComponent`.

Also how I would reference the mountNode, assuming that I'm trying to load this navbar up into the App container. My code is located at https://github.com/kecorbin/react-collins-ui if anyone could help a n00b. I apologize if this doesn't make sense, I'm very new to React, but love what I'm seeing from this starter!!!

Issue with programmatically changing routes

First off, thanks for creating a clean and well-documented starter app. We are in the process of migrating our existing code to use the tools provided here.

We are running into an issue with React Router v4 when trying to navigate to another route programmatically via push. At first we tried history.push(...), but that gave us errors saying push was undefined.

After looking through the issues, we found a thread that's relevant: #36. I think the issue was made before the full React Router v4 implementation was made to the boilerplate, but we went ahead with attempting the solution anyway. We added this to a connected component:

import { push } from 'react-router-redux'
...
const mapDispatchToProps = (dispatch) => {
  return {
    push: v => dispatch(push(v)),
    ...
  }
};

And tried changing routes via

this.props.push('/newroute')

Although the browser's URL bar changes location, but the page does not update. Can anyone tell me what's missing here?


Steps to reproduce:

  1. Replace ./src/containers/Home/index.js with the following:
/* eslint-disable react/sort-comp */
/* @flow */

import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import type { Connector } from 'react-redux';
import Helmet from 'react-helmet';
import { push } from 'react-router-redux';

import * as action from './action';
import type { Home as HomeType, Dispatch, Reducer } from '../../types';
import UserList from '../../components/UserList';
import styles from './styles.scss';

type Props = {
  home: HomeType,
  fetchUsersIfNeeded: () => void,
  push: () => void,
};

// Export this for unit testing more easily
export class Home extends PureComponent {
  props: Props;

  static defaultProps: {
    home: {
      readyStatus: 'USERS_INVALID',
      list: null,
    },
    fetchUsersIfNeeded: () => {},
  };

  componentDidMount() {
    this.props.fetchUsersIfNeeded();
  }

  renderUserList = () => {
    const { home } = this.props;

    if (!home.readyStatus || home.readyStatus === action.USERS_INVALID ||
      home.readyStatus === action.USERS_REQUESTING) {
      return <p>Loading...</p>;
    }

    if (home.readyStatus === action.USERS_FAILURE) {
      return <p>Oops, Failed to load list!</p>;
    }

    return <UserList list={home.list} />;
  }

  render() {
    return (
      <div className={styles.Home}>
        <Helmet title="Home" />
        {this.renderUserList()}
        <button onClick={() => this.props.push('/UserInfo/6')}>Click this button</button>
      </div>
    );
  }
}

const connector: Connector<{}, Props> = connect(
  ({ home }: Reducer) => ({ home }),
  (dispatch: Dispatch) => ({
    fetchUsersIfNeeded: () => dispatch(action.fetchUsersIfNeeded()),
    push: a => dispatch(push(a)),
  }),
);

export default connector(Home);
  1. Run the project and click the "Click this button"
  2. URL will change but the component won't update

css modules and fontawesome

I'm trying to make fontawesome work for my css modules configuration, but I'm getting some errors:

Failed to decode downloaded font: http://localhost:3000/
(index):1 OTS parsing error: invalid version tag

It appears the client is trying to fetch the font from the root url of the app, which is incorrect.

Benefits of testing with Jest

What are your thoughts on moving testing to Jest? Dan Abramov β€” the author of Redux β€” has been working on the framework recently and they've pushed a number of big updates over the past few months (snapshot testing, performance improvements, integrated coverage reporting, upgraded CLI, etc).

Hot update reducers on server side

First of all I want to thank you for this awesome boilerplate.
I run server with store which contains initial state from my reducers.
But when I change initial state in one of my reducers, it doesn't update.
I was trying to achieve reloading with nodeman. It watched folder with reducers and reload when they change, but nodemon reload server too slow.
There are some solutions for it such as piping, chokidar and so on.
It needs Browsersync also.
It would be great if you added it in this boilerplate.
Thanks.

Browsersync

Hi @wellyshen. Could you add browsersync for able to testing app in dev mode on mobile devices?

Do all containers have to have a fetchData method?

Do all containers have to have a fetchData method? In server.js, it looks like you are expecting every container to have a fetchData method if it wants access to "dispatch". What do I do for containers that don't need to fetch data but still need access to store.dispatch?

ReferenceError: initialState is not defined

I am sorry for this, actually there is no error with your boilerplate. Let me explain.
I have cloned your boilerplate to use for my Recipebook(the app i am building in educational purposes in order to get solid understanding of redux ecosystem).
So i have changed boilerplate to fit my needs.
After that i run npm run build successfully.
And then i get error(screenshot below) on 'npm start'.
I have created Recipebook repo where i have uploaded my code.
I know i asking for too much but i am eated my braines trying to figure this out.
Can you please check my repo and help me figure out how to fix this error.
Thanks in advance!
recipebook error

Route-based code splitting

Hi,

Sorry for the beginner question, does this setup support code splitting out of the box (i.e. different JS bundle per page)? If not, how can I go about doing that?

This is a terrific package by the way. I've been looking around and this is by far the most updated and cleanest setup. Can't wait to dig further into it.

Cheers

Autobuilding in dev mode stops on stylelint error

If running in dev mode (npm start), and you save a scss file that doesn't meet the lint requirements, an unhandled promise stops to autobuilding and it can only be restarted again by restarting dev mode (CTRL+C and npm start).

Below is an example of the error:

webpack built 2c46991acd218b194d93 in 9297ms

src/components/UserList/styles.scss
 5:3  βœ–  Unexpected empty line before nested rule   rule-nested-empty-line-before


(node:30980) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Failed because of a stylelint error.

ERROR in Entry module not found: Error: Can't resolve 'babel'

Hi!

I just tried to start the react-cool-starter project, but I have some troubles.

I get the following message: webpack-isomorphic-tools (waiting for the first webpack build to finish) when I'm running npm start. So I runned npm run build to fix it. Then I've got this error: ERROR in Entry module not found: Error: Can't resolve 'babel' in '/PATH/react-cool-starter'.

Do you have any ideas?

Thanks for your time.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.