- React Hooks based
- Redux
redux-thunk
- React Router
- Sass supported
- Image Loading
- Code Splitting
- Create a Component,
importit in/pages/index.jsusingwithSplitting()
- Create a Component,
- Environment Variables
- Webpack Dev Server
- Storybook for React
- Github Page Deployment
- Other optimizations for build
index.htmlfor initial entry point to users/assetsfor all static resources used in this web page
/componentsfor presentational unit components/basefor large components/commonfor minimal component unitComponent.jsComponent.cssComponent.stories.jsComponent.test.jsindex.js
/containersfor container components/pagesfor page per each routings/commonfor functional pages- All routings indexed in
App.js - Code Splitting enabled
/utilsfor utility functions/reduxfor redux store and reducers settings- Provided in Ducks pattern using Redux Toolkit
/configfor environment variables setting and Webpack config files- Put your
.envfile in/config/envdirectory
- Put your
- Run
npm installto provide required npm modules - (Optional) Go to
/config/envand make.envfile for your project
You can inject your custom environment variables in your project.
The .env file should be located in /config/env directory.
The project will inject { __NOT_USED__: undefined } environment variable object as a default. You don't necessarily have to use .env file.
- Run
npm run build - Use a build output from
/builddirectory
- Run
npm run dev - Visit
http://localhost:3000(Automatically opens)
- Run
npm run storybook - Visit Storybook UI (Automatically opens)
- Add following values in
.envfile (/config/env/.env):
# .env
# replace contents inside the angle brackets with your own
REPO_NAME=<GITHUB_REPOSITORY_NAME>
REPO_URL=https://<GITHUB_ID>.github.io/<GITHUB_REPOSITORY_NAME>
- Run
npm run build:github - Include the output
/docsin themasterbranch of your project git push origin master- Go to your repository page, navigate into [Settings → GitHub Pages → Source], and choose
master branch /docs folder.
The resulting page will look like this.
- Package version updates
- Migrated to React Hooks
- Migrated to Redux Toolkit
- Fixed Storybook configurations
- Enabled React Hot Loader
- Changed code convention (indentation, semicolon)
- Changed directory structure
- Changed NPM scripts
- Changed usage for Github Page Deployment
- Temporarily disabled Storybook (waiting for this issue being fixed)
- added explanation for 'Hosting on Github Pages'
- fixed typo
webpack.config.js- used
pathmodule consistently to support non-POSIX path
- used
- added support for multi-routing for Github Page Deployment
- added html templates for Github Page Deployment
- fixed typo and added modification in README.md
- added Webpack config files
webpack.config.dev.jsfor development only- added HMR and Sourcemap options
- modified npm scripts along with new Webpack config files
- added Github Page deployment script and settings
- Currently for only a single routing page
- added custom Environment Variables settings
- added warning message if
.envis not provided or empty when webpack builds
- added warning message if
- separated Webpack config files in
/configdirectory - updated module (html-webpack-plugin)
- added Sass support
- added
webpack.config.jsfor Storybook config
- added
- changed
.cssto.scss
- added build option for production build
- added
url-loaderand support for image loading from server's directory
- added tips for using react-router's
withRouter()HoC.
- added
/templatesdirectory: general purpose template components- example:
<Article />component
- example:
- bugfix when using
react-routerwithwds - added example for
react-router - added Tips section:
- relevant tips
- added comments with core logic explanations
- added
redux-thunk, loaders for style - added Storybook features
- added
reduxbasic sample codes - changed directory structures
Initial boilerplate checkout
- If you want to use images in pages
- Tips for using React Router
- Embedding Environment Variables
- Hosting on Github Pages
You can simply load static images which are uploaded in web server's directory by using specific URI indicating the resources.
<img src="assets/images/BlueMountains.jpg" />Files have to be located in public/assets directory, and the URI should include prefix of assets/. Subdirectories are able to customized. See webpack.config.js for more detailed configurations.
As Webpack Dev Server(WDS) does not serve index.html for routes except / as default config, we should set relevant configuration.
// webpack.config.js
module.exports = {
output: {
publicPath: '/'
},
// ...
devServer: {
histroyApiFallback: true
}
}You should set publicPath property to /, so that the WDS can understand real root (/) even when you are on subroutes. See this article.
If your component use withRouter() HoC and use relevant props within itself(i.e. history.push()), that component has to be wrapped with <Router />. You can use <MemoryRouter /> to mock the routing environment.
// Component.stories.js
import { MemoryRouter } from 'react-router'
storiesOf('MainButton', module)
.addDecorator(story => <MemoryRouter initialEntries={['/']}>{story()}</MemoryRouter>)
.add('default', () => (
<ComponentWithRouter />
)
)(To be added)
When it comes to hosting React application with React Router on Github Page, 2 issues have to be handled:
If all routing requests are handled on the client side by your React application, your React hosting server has to return index.html file for all requests. Then your routing module(in this case, React Router) will render the corresponding page for the requested route path.
However, the Github Page's server is not particularly set for a React application, and a user cannot customize the server's settings. If the application requests for a path which does not have corresponding page in the project directory, the server will return plain 404.html page, making your React Router useless.
Luckilly, there is already a good solution for this issue. To apply this solution, we have to put some extra codes in index.html and 404.html. You can check the assets used to generate HTML files in public/gh-pages, and bundling script in config/webpack.config.gh-pages.js.
If you have a repository on Github and want to deploy your static web page via Github Page, the site will have a public URL like below:
<USERNAME>.github.io/<REPOSITORY_NAME>
This means the entry file for your web application will be served under the URL above which containes /<REPOSITORY_NAME> at back. Usually the URL slug after the first / have to be considered as a top-level route path, but that is not the case here. It is a part of the public URL.
On the other hand, React Router will recognize the React application's public URL like below:
<USERNAME>.github.io
This is because React Router consider the application's public URL as its domain name as default. When a request occurs under this setting, the application won't be able to gather static assets needed to render the page, nor route between internal pages.
To fix this, we can fix either the server or the client-side app, but we cannot touch the server, as I mentioned on issue #1. So I used basename props and always put /<REPOSITORY_NAME> path in front of all the URLs generated by React Router.
// example code
<BrowserRouter basename="/cadenzah" />
<Link to="/dev" /> // renders <a href="/calendar/dev">Aside from URL routing, static assets served by your server - the bundled .js / .css files is requested by relative path in HTML files. Still, those files cannot be located properly, because HTML assumes the site's base URL(document.baseURI) as location.href as default, and use relative path with this setting.
Even though location.href changes each time routing occurs, the location for the static assets does not change because location.href is modified by client-side script, not the server, and the assets remains the same. As a result, we should set document.baseURI to the fixed value of the site's initial public URL so that our asset files can be located properly. Otherwise, the assets needed to render the screen cannot be loaded and the screen will be blank.
I added <base> tag to manage this issue. Webpack dynamically injects the base URL for our Github Page hosting URL when generating HTML files(htmlWebpackPlugin.options object).
<!-- public/gh-pages/index.ejs -->
...
<% if (htmlWebpackPlugin.options.basename) { %>
<base href="<%= htmlWebpackPlugin.options.basename %>"><%
} %>
...You can see the full code in public/gh-pages/index.ejs and config/webpack.config.gh-pages.js.