├── .editorconfig ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── code-of-conduct.md ├── docs ├── 1066d09f5f7d246e7fe83a4213a25b46.svg ├── 2fd8acdbbbc8e917fe4bcfb1897a4812.svg ├── 36b0c331ffa178baa751f03e0b0faa7a.png ├── 6a0c6735f0974c8f5f3742739827c887.png ├── 93925b42c5d9e0eedd76ff43f6394cc4.png ├── 960b7d80086730b0220855be5a22ccfc.png ├── assets │ ├── 0.db65d0c4242176afb2ae.js │ ├── 1.1fa2876aca97c4e791b0.js │ ├── 2.98d6fa879758a62cedd3.js │ ├── 3.142e9f71581d931504a0.js │ ├── app.0e7866b38396af465a2c.js │ └── vendor.0e7866b38396af465a2c.js └── index.html ├── index.hbs ├── package.json ├── postcss.config.js ├── src ├── components │ ├── App.js │ ├── DataWrapper.js │ ├── Footer.js │ ├── Header.js │ ├── Home.js │ ├── Login.js │ ├── Member.js │ ├── Nav.js │ ├── NotFound.js │ ├── Protected.js │ └── ui │ │ ├── ActiveLink.js │ │ └── Button.js ├── images │ ├── boilerplate-logo.svg │ ├── bull-icon.svg │ ├── mobx-logo.png │ ├── react-logo.png │ ├── react-router-logo.png │ └── webpack-logo.png ├── index.js ├── stores │ ├── AppState.js │ └── stores.js ├── styles │ ├── atoms │ │ └── _buttons.scss │ ├── base │ │ ├── _base.scss │ │ ├── _typography.scss │ │ └── _variables.scss │ ├── components │ │ ├── _footer.scss │ │ ├── _header.scss │ │ └── _nav.scss │ ├── main.scss │ ├── pages │ │ └── _home.scss │ └── tools │ │ └── _functions.scss └── utils │ └── constants.js ├── webpack.config.js ├── webpack.config.production.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_size = 2 8 | indent_style = space 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Development folders and files # 2 | ################################# 3 | .tmp/ 4 | _ignore/ 5 | dist/ 6 | node_modules/ 7 | 8 | # Folder config file # 9 | ###################### 10 | Desktop.ini 11 | 12 | # Folders for inspiration & notes # 13 | ################################### 14 | _moodboard/ 15 | _notes/ 16 | 17 | # Log files & folders # 18 | ####################### 19 | logs/ 20 | *.log 21 | npm-debug.log* 22 | .npm 23 | 24 | # Packages # 25 | ############ 26 | # it's better to unpack these files and commit the raw source 27 | # git has its own built in compression methods 28 | *.7z 29 | *.dmg 30 | *.gz 31 | *.iso 32 | *.jar 33 | *.rar 34 | *.tar 35 | *.zip 36 | 37 | # Photoshop & Illustrator files # 38 | ################################# 39 | *.ai 40 | *.eps 41 | *.psd 42 | 43 | # Windows & Mac file caches # 44 | ############################# 45 | .DS_Store 46 | Thumbs.db 47 | ehthumbs.db 48 | 49 | # Windows shortcuts # 50 | ##################### 51 | *.lnk 52 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | docs/ 3 | .editorconfig 4 | code-of-conduct.md 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Alex Devero (alexdevero.com). 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 🚧 This repository is no longer maintained.🚧 3 |
4 |

5 | 6 |

7 | 8 |
9 |
10 |

11 | 12 |

13 | 17 | Dependency Status 18 | devDependency Status 19 | Releases 20 |

21 | 22 |

23 | 24 | 25 | 26 | Built by DEVERO 27 | MIT License 28 |

29 | 30 | 31 | 32 | ## React - MobX - React-Router - Webpack Boilerplate (heroku-ready) 33 | 34 | React, MobX, React-Router and Webpack boilerplate with async routes. This boilerplate is also ready for deploying your app to Heroku. 35 | 36 | ### Table of contents 37 | 38 | * [Install](#install) 39 | * [Usage](#usage) 40 | * [Support this project](#support-this-project) 41 | * [Code of Conduct](#code-of-conduct) 42 | * [License](#license) 43 | 44 | ### Install 45 | 46 | #### Clone this repo 47 | 48 | ``` 49 | $ git clone https://github.com/alexdevero/react-mobx-react-router-boilerplate.git 50 | ``` 51 | 52 | #### Install dependencies 53 | 54 | ``` 55 | yarn 56 | ``` 57 | or 58 | ``` 59 | npm install 60 | ``` 61 | 62 | ### Usage 63 | 64 | #### Start project on local server (go to localhost:1337) 65 | 66 | ``` 67 | yarn start 68 | ``` 69 | or 70 | ``` 71 | npm start 72 | ``` 73 | 74 | #### Build project (in "dist" folder): 75 | 76 | ``` 77 | yarn run build 78 | ``` 79 | or 80 | ``` 81 | npm run build 82 | ``` 83 | 84 | #### Preview minified production-ready bundle (go to localhost:3000) 85 | 86 | ``` 87 | yarn run preview 88 | ``` 89 | or 90 | ``` 91 | npm run preview 92 | ``` 93 | 94 | #### Async component loading 95 | 96 | Components are now loaded async with react-router-loader and the store is injected via MobX Provider. 97 | 98 | ### Support this project 99 | 100 | 101 | 102 | Development and maintenance of this project takes a lot of time. If you want to support this project and help its author, there are few ways you can do it: 103 | 104 | - Starring and sharing the project 105 | - [![Donate](https://img.shields.io/badge/Donate-Paypal-brightgreen.svg?colorB=259cd2)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YKLGUUB34ASEL)—make one-time donations via PayPal. 106 | - [![Donate](https://img.shields.io/badge/Donate-Patreon-brightgreen.svg?colorB=f86213)](https://www.patreon.com/alexdevero)—set up monthly donation via Patreon and get interesting news about what I'm doing. 107 | - Releases—send bitcoins or ethereum to this address: `19jHGagJWeVvuNjN3kaBoAszXd9ea9gKzp`. 108 | 109 | Thank you! 110 | 111 | ### Code of Conduct 112 | 113 | [Contributor Code of Conduct](code-of-conduct.md). By participating in this project you agree to abide by its terms. 114 | 115 | ### License 116 | 117 | MIT © [Alex Devero](https://alexdevero.com). 118 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at deveroalex@gmail.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]. 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /docs/1066d09f5f7d246e7fe83a4213a25b46.svg: -------------------------------------------------------------------------------- 1 | module.exports = __webpack_public_path__ + "2fd8acdbbbc8e917fe4bcfb1897a4812.svg"; -------------------------------------------------------------------------------- /docs/2fd8acdbbbc8e917fe4bcfb1897a4812.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/36b0c331ffa178baa751f03e0b0faa7a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexdevero/react-mobx-react-router-boilerplate/dea097fa4b91a029d5a6761c2e6ba556218a5825/docs/36b0c331ffa178baa751f03e0b0faa7a.png -------------------------------------------------------------------------------- /docs/6a0c6735f0974c8f5f3742739827c887.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexdevero/react-mobx-react-router-boilerplate/dea097fa4b91a029d5a6761c2e6ba556218a5825/docs/6a0c6735f0974c8f5f3742739827c887.png -------------------------------------------------------------------------------- /docs/93925b42c5d9e0eedd76ff43f6394cc4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexdevero/react-mobx-react-router-boilerplate/dea097fa4b91a029d5a6761c2e6ba556218a5825/docs/93925b42c5d9e0eedd76ff43f6394cc4.png -------------------------------------------------------------------------------- /docs/960b7d80086730b0220855be5a22ccfc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexdevero/react-mobx-react-router-boilerplate/dea097fa4b91a029d5a6761c2e6ba556218a5825/docs/960b7d80086730b0220855be5a22ccfc.png -------------------------------------------------------------------------------- /docs/assets/0.db65d0c4242176afb2ae.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([0],{'./node_modules/css-loader/index.js?{"sourceMap":true}!./node_modules/postcss-loader/lib/index.js?{"sourceMap":true}!./node_modules/resolve-url-loader/index.js!./node_modules/sass-loader/lib/loader.js?{"sourceMap":true}!./src/styles/main.scss':function(n,e,r){e=n.exports=r("./node_modules/css-loader/lib/css-base.js")(!0),e.push([n.i,"*,\n*:before,\n*:after {\n -webkit-box-sizing: inherit;\n box-sizing: inherit;\n}\n\nhtml {\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n}\n\nbody {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-flex: 1;\n -ms-flex: 1;\n flex: 1;\n -webkit-box-orient: vertical;\n -webkit-box-direction: normal;\n -ms-flex-direction: column;\n flex-direction: column;\n overflow-y: scroll;\n padding: 0;\n margin: 0;\n}\n\n.wrapper {\n min-height: 100vh;\n}\n\nhtml {\n font-family: 'Roboto', Helvetica, sans-serif;\n font-size: 100%;\n font-style: normal;\n font-weight: normal;\n line-height: 1.6;\n -webkit-font-smoothing: antialiased;\n text-rendering: optimizeLegibility;\n}\n\nbody {\n color: #111;\n line-height: inherit;\n}\n\nh2,\nh3,\nh4,\nh5,\nh6 {\n margin-bottom: 12.8px;\n margin-bottom: 0.8rem;\n}\n\nh5,\nh6 {\n margin-top: 64px;\n margin-top: 4rem;\n font-size: 20px;\n font-size: 1.25rem;\n line-height: 32px;\n line-height: 2rem;\n}\n\nh1 {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 80px;\n font-size: 5rem;\n line-height: 128px;\n line-height: 8rem;\n}\n\nh2 {\n margin-top: 64px;\n margin-top: 4rem;\n font-size: 40px;\n font-size: 2.5rem;\n line-height: 48px;\n line-height: 3rem;\n}\n\nh3 {\n margin-top: 51.2px;\n margin-top: 3.2rem;\n font-size: 28.75px;\n font-size: 1.79688rem;\n line-height: 32px;\n line-height: 2rem;\n}\n\nh4 {\n margin-top: 38px;\n margin-top: 2.375rem;\n font-size: 24px;\n font-size: 1.5rem;\n line-height: 32px;\n line-height: 2rem;\n}\n\nh1 + h2 {\n margin-top: 25.6px;\n margin-top: 1.6rem;\n}\n\nh2 + h3,\nh3 + h4,\nh4 + h5 {\n margin-top: 12.8px;\n margin-top: 0.8rem;\n}\n\nh5 + h6 {\n margin-top: -12.8px;\n margin-top: -0.8rem;\n}\n\nsmall,\n.text--small {\n font-size: 80%;\n}\n\na {\n color: rgba(0, 0, 0, .9);\n text-decoration: none;\n cursor: pointer;\n}\n\na:hover {\n color: black;\n}\n\na.active {\n color: black;\n}\n\n.btn {\n position: relative;\n display: inline-block;\n padding-left: 12px;\n padding-left: 0.75rem;\n font-weight: 400;\n line-height: 1.25;\n padding: 16px 22px;\n padding: 1rem 1.375rem;\n font-size: 18px;\n font-size: 1.125rem;\n font-weight: 600;\n color: #fff;\n background: #111;\n border: 2px solid #000;\n}\n\n.btn:hover {\n color: #111;\n background: #fff;\n}\n\n.header {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-flex: 0;\n -ms-flex: 0 1 auto;\n flex: 0 1 auto;\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n padding: 0 24px;\n width: 100%;\n height: 60px;\n}\n\nfooter {\n padding: 18px 0;\n padding: 1.125rem 0;\n width: 100%;\n font-size: 13px;\n font-size: 0.8125rem;\n color: #666;\n text-align: center;\n border-top: 1px solid #eee;\n}\n\nfooter a {\n margin-left: .5ch;\n}\n\nfooter a:first-child {\n margin-right: .5ch;\n}\n\nnav {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-flex: 1;\n -ms-flex: 1;\n flex: 1;\n}\n\nnav a {\n margin-right: 24px;\n font-weight: 500;\n color: rgba(0, 0, 0, .5);\n}\n\nnav a:hover {\n color: black;\n}\n\nnav .active {\n color: black;\n}\n\n.home main {\n padding: 48px 24px;\n padding: 3rem 1.5rem;\n}\n\n.page__top {\n padding-top: 96px;\n padding-top: 6rem;\n padding-bottom: 96px;\n padding-bottom: 6rem;\n text-align: center;\n}\n\n.page__top h1 {\n margin-bottom: 12px;\n margin-bottom: 0.75rem;\n font-size: 32px;\n font-size: 2rem;\n line-height: 1.6;\n}\n\n.page__top .btn {\n margin-top: 12px;\n margin-top: 0.75rem;\n margin-right: auto;\n margin-left: auto;\n}\n\n.boilerplate-logo {\n clear: both;\n display: block;\n -webkit-box-flex: 0;\n -ms-flex: none;\n flex: none;\n overflow: hidden;\n margin-bottom: 24px;\n margin-bottom: 1.5rem;\n width: 100%;\n height: 112px;\n height: 7rem;\n background: url("+r("./src/images/bull-icon.svg")+");\n background-repeat: no-repeat;\n background-position: center;\n background-size: 7rem;\n}\n\n.main__header {\n padding-bottom: 72px;\n width: 100%;\n color: #000;\n text-align: center;\n}\n\nhr {\n margin: 24px auto 0;\n max-width: 96px;\n height: 1px;\n color: #ddd;\n background-color: #ddd;\n border: none;\n}\n\n.main__content {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -ms-flex-wrap: wrap;\n flex-wrap: wrap;\n -webkit-box-pack: center;\n -ms-flex-pack: center;\n justify-content: center;\n width: 100%;\n}\n\n.main__item {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-flex: 0;\n -ms-flex: 0 1 auto;\n flex: 0 1 auto;\n -webkit-box-orient: vertical;\n -webkit-box-direction: normal;\n -ms-flex-flow: column nowrap;\n flex-flow: column nowrap;\n width: 100%;\n text-align: center;\n}\n\n.main__item h4 {\n margin-top: 16px;\n margin-top: 1rem;\n}\n\n.main__item-logo {\n display: block;\n margin-right: auto;\n margin-left: auto;\n width: 48px;\n width: 3rem;\n height: 48px;\n height: 3rem;\n background: url("+r("./src/images/react-logo.png")+");\n background-repeat: no-repeat;\n background-size: contain;\n}\n\n.main__item-logo.mobx {\n background: url("+r("./src/images/mobx-logo.png")+");\n background-repeat: no-repeat;\n background-size: contain;\n}\n\n.main__item-logo.reactrouter {\n background: url("+r("./src/images/react-router-logo.png")+");\n background-repeat: no-repeat;\n background-size: contain;\n}\n\n.main__item-logo.webpack {\n background: url("+r("./src/images/webpack-logo.png")+");\n background-repeat: no-repeat;\n background-size: contain;\n}\n\n.main__extras {\n text-align: center;\n}\n\n.main__extras ul {\n padding: 0;\n margin: 24px 0 0;\n margin: 1.5rem 0 0;\n list-style-type: none;\n}\n\n@media screen and (min-width: 961px) {\n .home main {\n margin: 0 auto;\n width: 100%;\n max-width: 60rem;\n }\n}\n\n@media (min-width: 555px) {\n .main__item {\n max-width: calc(50% - 48px);\n }\n\n .main__item:nth-of-type(2n+2) {\n margin-right: 3rem;\n margin-left: 3rem;\n }\n}\n\n@media (min-width: 555px) and (max-width: 991px) {\n .main__item:nth-of-type(n+3) {\n margin-top: 3rem;\n }\n}\n\n@media (min-width: 992px) {\n .main__item {\n max-width: calc(33.33333% - 32px);\n }\n\n .main__item:nth-of-type(2) {\n margin-right: 3rem;\n margin-left: 3rem;\n }\n\n .main__item:last-of-type {\n margin-top: 1.625rem;\n }\n}\n\n","",{version:3,sources:["E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/base/_base.scss","E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/main.scss","E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/base/_typography.scss","E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/atoms/_buttons.scss","E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/components/_header.scss","E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/components/_footer.scss","E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/components/_nav.scss","E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/E:/Devero-Laboratories/WEB/my-experiments-and-projects/react-mobx-react-router-boilerplate/src/styles/pages/_home.scss"],names:[],mappings:"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",file:"main.scss",sourcesContent:["*,\r\n*:before,\r\n*:after {\r\n box-sizing: inherit;\r\n}\r\n\r\nhtml {\r\n box-sizing: border-box;\r\n}\r\n\r\nbody {\r\n display: flex;\r\n flex: 1;\r\n flex-direction: column;\r\n overflow-y: scroll;\r\n padding: 0;\r\n margin: 0;\r\n}\r\n\r\n.wrapper {\r\n min-height: 100vh;\r\n}\r\n","*,\n*:before,\n*:after {\n box-sizing: inherit;\n}\n\nhtml {\n box-sizing: border-box;\n}\n\nbody {\n display: flex;\n flex: 1;\n flex-direction: column;\n overflow-y: scroll;\n padding: 0;\n margin: 0;\n}\n\n.wrapper {\n min-height: 100vh;\n}\n\nhtml {\n font-family: 'Roboto', Helvetica, sans-serif;\n font-size: 100%;\n font-style: normal;\n font-weight: normal;\n line-height: 1.6;\n -webkit-font-smoothing: antialiased;\n text-rendering: optimizeLegibility;\n}\n\nbody {\n color: #111;\n line-height: inherit;\n}\n\nh2,\nh3,\nh4,\nh5,\nh6 {\n margin-bottom: 0.8rem;\n}\n\nh5,\nh6 {\n margin-top: 4rem;\n font-size: 1.25rem;\n line-height: 2rem;\n}\n\nh1 {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 5rem;\n line-height: 8rem;\n}\n\nh2 {\n margin-top: 4rem;\n font-size: 2.5rem;\n line-height: 3rem;\n}\n\nh3 {\n margin-top: 3.2rem;\n font-size: 1.79688rem;\n line-height: 2rem;\n}\n\nh4 {\n margin-top: 2.375rem;\n font-size: 1.5rem;\n line-height: 2rem;\n}\n\nh1 + h2 {\n margin-top: 1.6rem;\n}\n\nh2 + h3,\nh3 + h4,\nh4 + h5 {\n margin-top: 0.8rem;\n}\n\nh5 + h6 {\n margin-top: -0.8rem;\n}\n\nsmall,\n.text--small {\n font-size: 80%;\n}\n\na {\n color: rgba(0, 0, 0, 0.9);\n text-decoration: none;\n cursor: pointer;\n}\n\na:hover {\n color: black;\n}\n\na.active {\n color: black;\n}\n\n.btn {\n position: relative;\n display: inline-block;\n padding-left: 0.75rem;\n font-weight: 400;\n line-height: 1.25;\n padding: 1rem 1.375rem;\n font-size: 1.125rem;\n font-weight: 600;\n color: #fff;\n background: #111;\n border: 2px solid #000;\n}\n\n.btn:hover {\n color: #111;\n background: #fff;\n}\n\n.header {\n display: flex;\n flex: 0 1 auto;\n align-items: center;\n padding: 0 24px;\n width: 100%;\n height: 60px;\n}\n\nfooter {\n padding: 1.125rem 0;\n width: 100%;\n font-size: 0.8125rem;\n color: #666;\n text-align: center;\n border-top: 1px solid #eee;\n}\n\nfooter a {\n margin-left: .5ch;\n}\n\nfooter a:first-child {\n margin-right: .5ch;\n}\n\nnav {\n display: flex;\n flex: 1;\n}\n\nnav a {\n margin-right: 24px;\n font-weight: 500;\n color: rgba(0, 0, 0, 0.5);\n}\n\nnav a:hover {\n color: black;\n}\n\nnav .active {\n color: black;\n}\n\n.home main {\n padding: 3rem 1.5rem;\n}\n\n@media screen and (min-width: 961px) {\n .home main {\n margin: 0 auto;\n width: 100%;\n max-width: 60rem;\n }\n}\n\n.page__top {\n padding-top: 6rem;\n padding-bottom: 6rem;\n text-align: center;\n}\n\n.page__top h1 {\n margin-bottom: 0.75rem;\n font-size: 2rem;\n line-height: 1.6;\n}\n\n.page__top .btn {\n margin-top: 0.75rem;\n margin-right: auto;\n margin-left: auto;\n}\n\n.boilerplate-logo {\n clear: both;\n display: block;\n flex: none;\n overflow: hidden;\n margin-bottom: 1.5rem;\n width: 100%;\n height: 7rem;\n background: url(./../images/bull-icon.svg);\n background-repeat: no-repeat;\n background-position: center;\n background-size: 7rem;\n}\n\n.main__header {\n padding-bottom: 72px;\n width: 100%;\n color: #000;\n text-align: center;\n}\n\nhr {\n margin: 24px auto 0;\n max-width: 96px;\n height: 1px;\n color: #ddd;\n background-color: #ddd;\n border: none;\n}\n\n.main__content {\n display: flex;\n flex-wrap: wrap;\n justify-content: center;\n width: 100%;\n}\n\n.main__item {\n display: flex;\n flex: 0 1 auto;\n flex-flow: column nowrap;\n width: 100%;\n text-align: center;\n}\n\n@media (min-width: 555px) {\n .main__item {\n max-width: calc(50% - 48px);\n }\n\n .main__item:nth-of-type(2n+2) {\n margin-right: 3rem;\n margin-left: 3rem;\n }\n}\n\n@media (min-width: 555px) and (max-width: 991px) {\n .main__item:nth-of-type(n+3) {\n margin-top: 3rem;\n }\n}\n\n@media (min-width: 992px) {\n .main__item {\n max-width: calc(33.33333% - 32px);\n }\n\n .main__item:nth-of-type(2) {\n margin-right: 3rem;\n margin-left: 3rem;\n }\n\n .main__item:last-of-type {\n margin-top: 1.625rem;\n }\n}\n\n.main__item h4 {\n margin-top: 1rem;\n}\n\n.main__item-logo {\n display: block;\n margin-right: auto;\n margin-left: auto;\n width: 3rem;\n height: 3rem;\n background: url(./../images/react-logo.png);\n background-repeat: no-repeat;\n background-size: contain;\n}\n\n.main__item-logo.mobx {\n background: url(./../images/mobx-logo.png);\n background-repeat: no-repeat;\n background-size: contain;\n}\n\n.main__item-logo.reactrouter {\n background: url(./../images/react-router-logo.png);\n background-repeat: no-repeat;\n background-size: contain;\n}\n\n.main__item-logo.webpack {\n background: url(./../images/webpack-logo.png);\n background-repeat: no-repeat;\n background-size: contain;\n}\n\n.main__extras {\n text-align: center;\n}\n\n.main__extras ul {\n padding: 0;\n margin: 1.5rem 0 0;\n list-style-type: none;\n}\n\n","html {\r\n font-family: 'Roboto', Helvetica, sans-serif;\r\n font-size: 100%;\r\n font-style: normal;\r\n font-weight: normal;\r\n line-height: 1.6;\r\n\r\n -webkit-font-smoothing: antialiased;\r\n text-rendering: optimizeLegibility;\r\n}\r\n\r\nbody {\r\n color: #111;\r\n line-height: inherit;\r\n}\r\n\r\nh2,\r\nh3,\r\nh4,\r\nh5,\r\nh6 {\r\n margin-bottom: remy(12.8px);\r\n}\r\n\r\nh5,\r\nh6 {\r\n margin-top: remy(64px);\r\n font-size: remy(20px);\r\n line-height: remy(32px);\r\n}\r\n\r\nh1 {\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n font-size: remy(80px);\r\n line-height: remy(128px);\r\n}\r\n\r\nh2 {\r\n margin-top: remy(64px);\r\n font-size: remy(40px);\r\n line-height: remy(48px);\r\n}\r\n\r\nh3 {\r\n margin-top: remy(51.2px);\r\n font-size: remy(28.75px);\r\n line-height: remy(32px);\r\n}\r\n\r\nh4 {\r\n margin-top: remy(38px);\r\n font-size: remy(24px);\r\n line-height: remy(32px);\r\n}\r\n\r\nh1 + h2 {\r\n margin-top: remy(25.6px);\r\n}\r\n\r\nh2 + h3,\r\nh3 + h4,\r\nh4 + h5 {\r\n margin-top: remy(12.8px);\r\n}\r\n\r\nh5 + h6 {\r\n margin-top: remy(-12.8px);\r\n}\r\n\r\nsmall,\r\n.text--small {\r\n font-size: 80%;\r\n}\r\n\r\na {\r\n color: rgba(#000, .9);\r\n text-decoration: none;\r\n cursor: pointer;\r\n\r\n &:hover {\r\n color: rgba(#000, 1);\r\n }\r\n\r\n &.active {\r\n color: rgba(#000, 1);\r\n }\r\n}\r\n","// Buttons atom\r\n\r\n.btn {\r\n position: relative;\r\n display: inline-block;\r\n padding-left: remy(12px);\r\n font-weight: 400;\r\n line-height: 1.25;\r\n padding: remy(16px) remy(22px);\r\n font-size: remy(18px);\r\n font-weight: 600;\r\n color: #fff;\r\n background: #111;\r\n border: 2px solid #000;\r\n\r\n &:hover {\r\n color: #111;\r\n background: #fff;\r\n }\r\n}\r\n","// Header component\r\n\r\n.header {\r\n display: flex;\r\n flex: 0 1 auto;\r\n align-items: center;\r\n padding: 0 24px;\r\n width: 100%;\r\n height: 60px;\r\n}\r\n","// Footer component\r\n\r\nfooter {\r\n padding: remy(18px) 0;\r\n width: 100%;\r\n font-size: remy(13px);\r\n color: #666;\r\n text-align: center;\r\n border-top: 1px solid #eee;\r\n\r\n a {\r\n margin-left: .5ch;\r\n\r\n &:first-child {\r\n margin-right: .5ch;\r\n }\r\n }\r\n}\r\n","// Nav component\r\n\r\nnav {\r\n display: flex;\r\n flex: 1;\r\n\r\n a {\r\n margin-right: 24px;\r\n font-weight: 500;\r\n color: rgba(#000, .5);\r\n\r\n &:hover {\r\n color: rgba(#000, 1);\r\n }\r\n }\r\n\r\n .active {\r\n color: rgba(#000, 1);\r\n }\r\n}\r\n","// Page Home\r\n\r\n.home {\r\n main {\r\n padding: remy(48px) remy(24px);\r\n\r\n @media screen and (min-width: 961px) {\r\n margin: 0 auto;\r\n width: 100%;\r\n max-width: remy(960px);\r\n }\r\n }\r\n}\r\n\r\n.page__top {\r\n padding-top: remy(96px);\r\n padding-bottom: remy(96px);\r\n text-align: center;\r\n\r\n h1 {\r\n margin-bottom: remy(12px);\r\n font-size: remy(32px);\r\n line-height: 1.6;\r\n }\r\n\r\n .btn {\r\n margin-top: remy(12px);\r\n margin-right: auto;\r\n margin-left: auto;\r\n }\r\n}\r\n\r\n.boilerplate-logo {\r\n clear: both;\r\n display: block;\r\n flex: none;\r\n overflow: hidden;\r\n margin-bottom: remy(24px);\r\n width: 100%;\r\n height: remy(112px);\r\n background: url(bull-icon.svg);\r\n background-repeat: no-repeat;\r\n background-position: center;\r\n background-size: remy(112px);\r\n}\r\n\r\n.main__header {\r\n padding-bottom: 72px;\r\n width: 100%;\r\n color: #000;\r\n text-align: center;\r\n}\r\n\r\nhr {\r\n margin: 24px auto 0;\r\n max-width: 96px;\r\n height: 1px;\r\n color: #ddd;\r\n background-color: #ddd;\r\n border: none;\r\n}\r\n\r\n.main__content {\r\n display: flex;\r\n flex-wrap: wrap;\r\n justify-content: center;\r\n width: 100%;\r\n}\r\n\r\n.main__item {\r\n display: flex;\r\n flex: 0 1 auto;\r\n flex-flow: column nowrap;\r\n width: 100%;\r\n text-align: center;\r\n\r\n @media (min-width: 555px) {\r\n max-width: calc(50% - 48px);\r\n\r\n &:nth-of-type(2n+2) {\r\n margin-right: remy(48px);\r\n margin-left: remy(48px);\r\n }\r\n }\r\n\r\n @media (min-width: 555px) and (max-width: 991px) {\r\n &:nth-of-type(n+3) {\r\n margin-top: remy(48px);\r\n }\r\n }\r\n\r\n @media (min-width: 992px) {\r\n max-width: calc(33.33333% - 32px);\r\n\r\n &:nth-of-type(2) {\r\n margin-right: remy(48px);\r\n margin-left: remy(48px);\r\n }\r\n\r\n &:last-of-type {\r\n margin-top: remy(26px);\r\n }\r\n }\r\n\r\n h4 {\r\n margin-top: remy(16px);\r\n }\r\n}\r\n\r\n.main__item-logo {\r\n display: block;\r\n margin-right: auto;\r\n margin-left: auto;\r\n width: remy(48px);\r\n height: remy(48px);\r\n background: url(react-logo.png);\r\n background-repeat: no-repeat;\r\n background-size: contain;\r\n\r\n &.mobx {\r\n background: url(mobx-logo.png);\r\n background-repeat: no-repeat;\r\n background-size: contain;\r\n }\r\n\r\n &.reactrouter {\r\n background: url(react-router-logo.png);\r\n background-repeat: no-repeat;\r\n background-size: contain;\r\n }\r\n\r\n &.webpack {\r\n background: url(webpack-logo.png);\r\n background-repeat: no-repeat;\r\n background-size: contain;\r\n }\r\n}\r\n\r\n.main__extras {\r\n text-align: center;\r\n\r\n ul {\r\n padding: 0;\r\n margin: remy(24px) 0 0;\r\n list-style-type: none;\r\n }\r\n}\r\n"],sourceRoot:""}])},"./node_modules/css-loader/lib/css-base.js":function(n,e){function r(n,e){var r=n[1]||"",A=n[3];if(!A)return r;if(e&&"function"==typeof btoa){var o=t(A);return[r].concat(A.sources.map(function(n){return"/*# sourceURL="+A.sourceRoot+n+" */"})).concat([o]).join("\n")}return[r].join("\n")}function t(n){return"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(n))))+" */"}n.exports=function(n){var e=[];return e.toString=function(){return this.map(function(e){var t=r(e,n);return e[2]?"@media "+e[2]+"{"+t+"}":t}).join("")},e.i=function(n,r){"string"==typeof n&&(n=[[null,n,""]]);for(var t={},A=0;A=0&&u.splice(e,1)}function a(n){var e=document.createElement("style");return n.attrs.type="text/css",m(e,n.attrs),o(n,e),e}function s(n){var e=document.createElement("link");return n.attrs.type="text/css",n.attrs.rel="stylesheet",m(e,n.attrs),o(n,e),e}function m(n,e){Object.keys(e).forEach(function(r){n.setAttribute(r,e[r])})}function l(n,e){var r,t,A,o;if(e.transform&&n.css){if(!(o=e.transform(n.css)))return function(){};n.css=o}if(e.singleton){var m=x++;r=f||(f=a(e)),t=p.bind(null,r,m,!1),A=p.bind(null,r,m,!0)}else n.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(r=s(e),t=d.bind(null,r,e),A=function(){i(r),r.href&&URL.revokeObjectURL(r.href)}):(r=a(e),t=c.bind(null,r),A=function(){i(r)});return t(n),function(e){if(e){if(e.css===n.css&&e.media===n.media&&e.sourceMap===n.sourceMap)return;t(n=e)}else A()}}function p(n,e,r,t){var A=r?"":t.css;if(n.styleSheet)n.styleSheet.cssText=C(e,A);else{var o=document.createTextNode(A),i=n.childNodes;i[e]&&n.removeChild(i[e]),i.length?n.insertBefore(o,i[e]):n.appendChild(o)}}function c(n,e){var r=e.css,t=e.media;if(t&&n.setAttribute("media",t),n.styleSheet)n.styleSheet.cssText=r;else{for(;n.firstChild;)n.removeChild(n.firstChild);n.appendChild(document.createTextNode(r))}}function d(n,e,r){var t=r.css,A=r.sourceMap,o=void 0===e.convertToAbsoluteUrls&&A;(e.convertToAbsoluteUrls||o)&&(t=E(t)),A&&(t+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(A))))+" */");var i=new Blob([t],{type:"text/css"}),a=n.href;n.href=URL.createObjectURL(i),a&&URL.revokeObjectURL(a)}var g={},h=function(n){var e;return function(){return void 0===e&&(e=n.apply(this,arguments)),e}}(function(){return window&&document&&document.all&&!window.atob}),b=function(n){var e={};return function(r){return void 0===e[r]&&(e[r]=n.call(this,r)),e[r]}}(function(n){return document.querySelector(n)}),f=null,x=0,u=[],E=r("./node_modules/style-loader/lib/urls.js");n.exports=function(n,e){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");e=e||{},e.attrs="object"==typeof e.attrs?e.attrs:{},e.singleton||(e.singleton=h()),e.insertInto||(e.insertInto="head"),e.insertAt||(e.insertAt="bottom");var r=A(n,e);return t(r,e),function(n){for(var o=[],i=0;i 2 | 3 | 4 | 5 | 6 | 7 | 8 | React MobX React-Router Boilerplate 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
62 | 63 | 64 | -------------------------------------------------------------------------------- /index.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | React MobX React-Router Boilerplate 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
62 | 63 | 64 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-mobx-react-router-boilerplate", 3 | "version": "1.1.10", 4 | "description": "React, MobX, React-Router, MobX-Router and Webpack (heroku-ready) boilerplate with async routes.", 5 | "main": "webpack.config.js", 6 | "engines": { 7 | "node": ">=9.0", 8 | "npm": ">=5.0", 9 | "yarn": ">=1.0" 10 | }, 11 | "scripts": { 12 | "start": "cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js --mode development", 13 | "build": "cross-env NODE_ENV=production rimraf ./dist && webpack --config webpack.config.production.js --mode production", 14 | "postinstall": "webpack --config ./webpack.config.production.js --mode production --display-error-details", 15 | "preview": "cross-env NODE_ENV=preview http-server ./dist -p 1234 -c-1", 16 | "test": "cross-env NODE_ENV=test echo \"Error: no test specified\" && exit 1" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/alexdevero/react-mobx-react-router-boilerplate.git" 21 | }, 22 | "keywords": [ 23 | "app", 24 | "ES6", 25 | "ES7", 26 | "heroku", 27 | "mobx", 28 | "mobx-router", 29 | "react", 30 | "react-router", 31 | "reactjs", 32 | "web app", 33 | "Webpack" 34 | ], 35 | "author": "Alex Devero (http://github.com/alexdevero)", 36 | "license": "MIT", 37 | "bugs": { 38 | "url": "https://github.com/alexdevero/react-mobx-react-router-boilerplate/issues" 39 | }, 40 | "homepage": "", 41 | "devDependencies": { 42 | "babel-core": "^6.26.3", 43 | "babel-loader": "^7.1.5", 44 | "babel-plugin-transform-async-to-generator": "^6.24.1", 45 | "babel-plugin-transform-decorators-legacy": "^1.3.5", 46 | "babel-polyfill": "^6.26.0", 47 | "babel-preset-es2015": "^6.24.1", 48 | "babel-preset-react": "^6.24.1", 49 | "babel-preset-stage-0": "^6.24.1", 50 | "cross-env": "^5.2.0", 51 | "css-loader": "^1.0.0", 52 | "css-mqpacker": "^7.0.0", 53 | "file-loader": "^2.0.0", 54 | "html-webpack-plugin": "^3.2.0", 55 | "image-webpack-loader": "^4.3.1", 56 | "mini-css-extract-plugin": "^0.4.3", 57 | "node-sass": "^4.9.3", 58 | "normalize.css": "^8.0.0", 59 | "postcss-cssnext": "^3.1.0", 60 | "postcss-loader": "^3.0.0", 61 | "react-hot-loader": "4.3.8", 62 | "resolve-url-loader": "^2.3.1", 63 | "rimraf": "^2.6.2", 64 | "sass-lint": "^1.12.1", 65 | "sass-loader": "^7.1.0", 66 | "style-loader": "^0.23.0", 67 | "url-loader": "^1.1.1", 68 | "webpack": "^4.19.1", 69 | "webpack-cli": "^3.1.0", 70 | "webpack-dev-server": "^3.1.8" 71 | }, 72 | "dependencies": { 73 | "axios": "^1.6.0", 74 | "http-server": "^0.11.1", 75 | "lazy-route": "^1.0.7", 76 | "mobx": "^5.1.2", 77 | "mobx-react": "^5.2.8", 78 | "mobx-react-devtools": "^6.0.3", 79 | "mobx-react-router": "^4.0.5", 80 | "react": "^16.5.2", 81 | "react-dom": "^16.5.2", 82 | "react-router-dom": "^4.3.1", 83 | "rfx-core": "^1.6.0", 84 | "whatwg-fetch": "^3.0.0" 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('postcss-cssnext')(), 4 | require('css-mqpacker')() 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /src/components/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Route, Link } from 'react-router-dom'; 3 | import { inject, observer } from 'mobx-react'; 4 | import LazyRoute from 'lazy-route'; 5 | import DevTools from 'mobx-react-devtools'; 6 | 7 | import Footer from './Footer'; 8 | import Header from './Header'; 9 | 10 | @inject('store', 'routing') 11 | @observer 12 | export default class App extends Component { 13 | constructor(props) { 14 | super(props); 15 | 16 | this.store = this.props.store; 17 | } 18 | 19 | authenticate(e) { 20 | if (e) e.preventDefault(); 21 | 22 | this.store.appState.authenticate(); 23 | } 24 | 25 | render() { 26 | const { 27 | authenticated, 28 | authenticating, 29 | timeToRefresh, 30 | refreshToken 31 | } = this.store.appState; 32 | 33 | return ( 34 |
35 |
36 | 37 | ( 41 | 42 | )} 43 | /> 44 | 45 | ( 49 | 50 | )} 51 | /> 52 | 53 | ( 57 | 58 | )} 59 | /> 60 | 61 |
62 |
63 | ); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/components/DataWrapper.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { inject, observer } from 'mobx-react'; 3 | import { Redirect } from 'react-router-dom'; 4 | 5 | export default function DataWrapper(Component) { 6 | @inject('store') 7 | @observer 8 | class DataFetcher extends Component { 9 | constructor(props) { 10 | super(props); 11 | this.store = this.props.store.appState; 12 | } 13 | 14 | componentDidMount() { 15 | console.log(this.props); 16 | let pathname = this.props.match.url; 17 | let id = this.props.match.id ? this.props.match.id : null; 18 | this.store.fetchData(pathname, id); 19 | } 20 | 21 | componentWillUnmount() { 22 | this.store.clearItems(); 23 | } 24 | 25 | render() { 26 | return ; 27 | } 28 | } 29 | return DataFetcher; 30 | } 31 | -------------------------------------------------------------------------------- /src/components/Footer.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { inject, observer } from 'mobx-react'; 3 | 4 | @inject('store') 5 | @observer 6 | export default class Footer extends Component { 7 | constructor(props) { 8 | super(props); 9 | 10 | this.store = this.props.store; 11 | } 12 | 13 | render() { 14 | return( 15 | 24 | ) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/components/Header.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { inject, observer } from 'mobx-react'; 3 | import { Link, withRouter } from 'react-router-dom'; 4 | 5 | import Nav from './Nav'; 6 | import Button from './ui/Button'; 7 | 8 | @inject('store') 9 | @observer 10 | export default class Header extends Component { 11 | constructor(props) { 12 | super(props); 13 | this.store = this.props.store.appState; 14 | } 15 | 16 | authenticate(e) { 17 | if (e) e.preventDefault(); 18 | 19 | console.log('CLICKED BUTTON'); 20 | 21 | this.store.authenticate(); 22 | } 23 | 24 | render() { 25 | const { authenticated } = this.store; 26 | 27 | return ( 28 |
29 |
36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/components/Home.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { inject, observer } from 'mobx-react'; 3 | 4 | @inject('store') 5 | @observer 6 | export default class Home extends Component { 7 | constructor(props) { 8 | super(props); 9 | this.store = this.props.store; 10 | } 11 | 12 | render() { 13 | const store = this.store; 14 | return ( 15 |
16 |
17 |
18 | 19 |

React MobX React-Router Boilerplate

20 | 21 |

A simple starting point for your React project with routing, data-fetching and state management!

22 | 23 | 32 |
33 | 34 |
35 |
36 |

Included libraries

37 | 38 |
39 |
40 | 41 |
42 |
43 |
44 | 45 |
46 | 50 |

MobX

51 |
52 | 53 | Reactive State Management 54 | 55 |

MobX provides simple and scalable state management.

56 |
57 |
58 | 59 |
60 |
61 | 62 |
63 | 67 |

React

68 |
69 | 70 | UI Library 71 | 72 |

React is a JavaScript library for building user interfaces.

73 |
74 |
75 | 76 |
77 |
78 | 79 |
80 | 84 |

React Router

85 |
86 | 87 | Routing Library 88 | 89 |

React Router helps you create routes for React in a declarative way.

90 |
91 |
92 | 93 |
94 |
95 | 96 |
97 | 98 |

Webpack

99 |
100 | 101 | Module Bundler 102 | 103 |

A bundler for javascript. Packs many modules into a few bundled assets.

104 |
105 |
106 |
107 | 108 |
109 |

Noteworthy

110 | 111 |
112 | 113 |
    114 |
  • ✓ Async Component Loading
  • 115 |
  • ✓ Code-splitting
  • 116 |
  • ✓ Extracted & autoprefixed CSS
  • 117 |
  • ✓ Modular SASS
  • 118 |
  • ✓ Maintained & up-to-date dependencies
  • 119 |
120 |
121 |
122 |
123 | ); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/components/Login.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { inject, observer } from 'mobx-react'; 3 | import { Redirect } from 'react-router-dom'; 4 | 5 | @inject('store') 6 | @observer 7 | export default class Login extends Component { 8 | render() { 9 | return ( 10 |
11 | Your login form here... 12 | {this.props.store.authenticated && 13 | !this.props.store.authenticating && 14 | } 15 |
16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/components/Member.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { inject, observer } from 'mobx-react'; 3 | 4 | @inject('store') 5 | @observer 6 | export default class Member extends Component { 7 | constructor(props) { 8 | super(props); 9 | this.store = this.props.store; 10 | } 11 | 12 | render() { 13 | const store = this.store; 14 | return ( 15 |
16 |
17 |

Members' area

18 |
19 |
20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/components/Nav.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { inject, observer } from 'mobx-react'; 3 | import { Route, Link } from 'react-router-dom'; 4 | import ActiveLink from './ui/ActiveLink'; 5 | 6 | @inject('store') 7 | @observer 8 | export default class Nav extends Component { 9 | constructor(props) { 10 | super(props); 11 | this.store = this.props.store.appState; 12 | } 13 | 14 | authenticate(e) { 15 | if (e) e.preventDefault(); 16 | this.props.store.authenticate(); 17 | } 18 | 19 | render() { 20 | const { authenticated, authenticating } = this.store; 21 | return ( 22 | 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/components/NotFound.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | export default class NotFound extends Component { 4 | render() { 5 | return ( 6 |
7 | 404 8 |
9 | ); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/components/Protected.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { inject, observer } from 'mobx-react'; 3 | import { Redirect } from 'react-router-dom'; 4 | 5 | export default function Protected(Component) { 6 | @inject('store') 7 | @observer 8 | class AuthenticatedComponent extends Component { 9 | constructor(props) { 10 | super(props); 11 | this.store = this.props.store.appState; 12 | } 13 | 14 | render() { 15 | const { authenticated, authenticating } = this.store; 16 | return ( 17 |
18 | {authenticated 19 | ? 20 | : !authenticating && !authenticated 21 | ? 27 | : null} 28 |
29 | ); 30 | } 31 | } 32 | return AuthenticatedComponent; 33 | } 34 | -------------------------------------------------------------------------------- /src/components/ui/ActiveLink.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Route, Link } from 'react-router-dom'; 3 | 4 | const ActiveLink = ({ to, activeOnlyWhenExact, ...rest }) => ( 5 | ( 9 | 10 | )} 11 | /> 12 | ); 13 | 14 | export default ActiveLink; 15 | -------------------------------------------------------------------------------- /src/components/ui/Button.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { observer } from 'mobx-react'; 3 | 4 | const Button = ({ ...props }) => { 5 | return {props.title}; 6 | }; 7 | 8 | export default Button; 9 | -------------------------------------------------------------------------------- /src/images/boilerplate-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | React.js_logo 5 | Created with Sketch. 6 | 7 | 8 | 16 | 17 | -------------------------------------------------------------------------------- /src/images/bull-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/mobx-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexdevero/react-mobx-react-router-boilerplate/dea097fa4b91a029d5a6761c2e6ba556218a5825/src/images/mobx-logo.png -------------------------------------------------------------------------------- /src/images/react-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexdevero/react-mobx-react-router-boilerplate/dea097fa4b91a029d5a6761c2e6ba556218a5825/src/images/react-logo.png -------------------------------------------------------------------------------- /src/images/react-router-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexdevero/react-mobx-react-router-boilerplate/dea097fa4b91a029d5a6761c2e6ba556218a5825/src/images/react-router-logo.png -------------------------------------------------------------------------------- /src/images/webpack-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexdevero/react-mobx-react-router-boilerplate/dea097fa4b91a029d5a6761c2e6ba556218a5825/src/images/webpack-logo.png -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import('./styles/main.scss'); 2 | import React from 'react'; 3 | import { render } from 'react-dom'; 4 | import { Router } from 'react-router-dom'; 5 | import { Provider } from 'mobx-react'; 6 | import { AppContainer } from 'react-hot-loader'; 7 | import { rehydrate, hotRehydrate } from 'rfx-core'; 8 | 9 | import { isProduction } from './utils/constants'; 10 | import App from './components/App'; 11 | import stores from './stores/stores'; 12 | 13 | import { RouterStore, syncHistoryWithStore } from 'mobx-react-router'; 14 | import createBrowserHistory from 'history/createBrowserHistory'; 15 | 16 | const store = rehydrate(); 17 | 18 | const renderApp = Component => { 19 | const browserHistory = createBrowserHistory(); 20 | const routeStore = new RouterStore(); 21 | const history = syncHistoryWithStore(browserHistory, routeStore); 22 | 23 | render( 24 | 25 | 26 | 27 | 28 | 29 | 30 | , 31 | document.getElementById('root') 32 | ); 33 | }; 34 | 35 | renderApp(App); 36 | 37 | if (module.hot) { 38 | module.hot.accept(() => renderApp(App)); 39 | } 40 | -------------------------------------------------------------------------------- /src/stores/AppState.js: -------------------------------------------------------------------------------- 1 | import { observable, action } from 'mobx'; 2 | import axios from 'axios'; 3 | 4 | export default class AppState { 5 | @observable authenticated; 6 | @observable authenticating; 7 | @observable items; 8 | @observable item; 9 | 10 | constructor() { 11 | this.authenticated = false; 12 | this.authenticating = false; 13 | this.items = []; 14 | this.item = {}; 15 | } 16 | 17 | async fetchData(pathname, id) { 18 | let { data } = await axios.get( 19 | `https://jsonplaceholder.typicode.com${pathname}` 20 | ); 21 | 22 | console.log(data); 23 | 24 | data.length > 0 ? this.setData(data) : this.setSingle(data); 25 | } 26 | 27 | @action setData(data) { 28 | this.items = data; 29 | } 30 | 31 | @action setSingle(data) { 32 | this.item = data; 33 | } 34 | 35 | @action clearItems() { 36 | this.items = []; 37 | this.item = {}; 38 | } 39 | 40 | @action authenticate() { 41 | return new Promise((resolve, reject) => { 42 | this.authenticating = true; 43 | 44 | setTimeout(() => { 45 | this.authenticated = !this.authenticated; 46 | this.authenticating = false; 47 | 48 | resolve(this.authenticated); 49 | }, 0); 50 | }); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/stores/stores.js: -------------------------------------------------------------------------------- 1 | import { store } from 'rfx-core'; 2 | 3 | import AppState from './AppState'; 4 | 5 | export default store.setup({ 6 | appState: AppState 7 | }); 8 | -------------------------------------------------------------------------------- /src/styles/atoms/_buttons.scss: -------------------------------------------------------------------------------- 1 | // Buttons atom 2 | 3 | .btn { 4 | position: relative; 5 | display: inline-block; 6 | padding-left: remy(12px); 7 | font-weight: 400; 8 | line-height: 1.25; 9 | padding: remy(16px) remy(22px); 10 | font-size: remy(18px); 11 | font-weight: 600; 12 | color: #fff; 13 | background: #111; 14 | border: 2px solid #000; 15 | 16 | &:hover { 17 | color: #111; 18 | background: #fff; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/styles/base/_base.scss: -------------------------------------------------------------------------------- 1 | *, 2 | *:before, 3 | *:after { 4 | box-sizing: inherit; 5 | } 6 | 7 | html { 8 | box-sizing: border-box; 9 | } 10 | 11 | body { 12 | display: flex; 13 | flex: 1; 14 | flex-direction: column; 15 | overflow-y: scroll; 16 | padding: 0; 17 | margin: 0; 18 | } 19 | 20 | .wrapper { 21 | min-height: 100vh; 22 | } 23 | -------------------------------------------------------------------------------- /src/styles/base/_typography.scss: -------------------------------------------------------------------------------- 1 | html { 2 | font-family: 'Roboto', Helvetica, sans-serif; 3 | font-size: 100%; 4 | font-style: normal; 5 | font-weight: normal; 6 | line-height: 1.6; 7 | 8 | -webkit-font-smoothing: antialiased; 9 | text-rendering: optimizeLegibility; 10 | } 11 | 12 | body { 13 | color: #111; 14 | line-height: inherit; 15 | } 16 | 17 | h2, 18 | h3, 19 | h4, 20 | h5, 21 | h6 { 22 | margin-bottom: remy(12.8px); 23 | } 24 | 25 | h5, 26 | h6 { 27 | margin-top: remy(64px); 28 | font-size: remy(20px); 29 | line-height: remy(32px); 30 | } 31 | 32 | h1 { 33 | margin-top: 0; 34 | margin-bottom: 0; 35 | font-size: remy(80px); 36 | line-height: remy(128px); 37 | } 38 | 39 | h2 { 40 | margin-top: remy(64px); 41 | font-size: remy(40px); 42 | line-height: remy(48px); 43 | } 44 | 45 | h3 { 46 | margin-top: remy(51.2px); 47 | font-size: remy(28.75px); 48 | line-height: remy(32px); 49 | } 50 | 51 | h4 { 52 | margin-top: remy(38px); 53 | font-size: remy(24px); 54 | line-height: remy(32px); 55 | } 56 | 57 | h1 + h2 { 58 | margin-top: remy(25.6px); 59 | } 60 | 61 | h2 + h3, 62 | h3 + h4, 63 | h4 + h5 { 64 | margin-top: remy(12.8px); 65 | } 66 | 67 | h5 + h6 { 68 | margin-top: remy(-12.8px); 69 | } 70 | 71 | small, 72 | .text--small { 73 | font-size: 80%; 74 | } 75 | 76 | a { 77 | color: rgba(#000, .9); 78 | text-decoration: none; 79 | cursor: pointer; 80 | 81 | &:hover { 82 | color: rgba(#000, 1); 83 | } 84 | 85 | &.active { 86 | color: rgba(#000, 1); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/styles/base/_variables.scss: -------------------------------------------------------------------------------- 1 | $color-primary: #ffec99; 2 | $color-secondary: #ffec99; 3 | $color-tertiary: #ffec99; 4 | -------------------------------------------------------------------------------- /src/styles/components/_footer.scss: -------------------------------------------------------------------------------- 1 | // Footer component 2 | 3 | footer { 4 | padding: remy(18px) 0; 5 | width: 100%; 6 | font-size: remy(13px); 7 | color: #666; 8 | text-align: center; 9 | border-top: 1px solid #eee; 10 | 11 | a { 12 | margin-left: .5ch; 13 | 14 | &:first-child { 15 | margin-right: .5ch; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/styles/components/_header.scss: -------------------------------------------------------------------------------- 1 | // Header component 2 | 3 | .header { 4 | display: flex; 5 | flex: 0 1 auto; 6 | align-items: center; 7 | padding: 0 24px; 8 | width: 100%; 9 | height: 60px; 10 | } 11 | -------------------------------------------------------------------------------- /src/styles/components/_nav.scss: -------------------------------------------------------------------------------- 1 | // Nav component 2 | 3 | nav { 4 | display: flex; 5 | flex: 1; 6 | 7 | a { 8 | margin-right: 24px; 9 | font-weight: 500; 10 | color: rgba(#000, .5); 11 | 12 | &:hover { 13 | color: rgba(#000, 1); 14 | } 15 | } 16 | 17 | .active { 18 | color: rgba(#000, 1); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/styles/main.scss: -------------------------------------------------------------------------------- 1 | // Tools 2 | @import 'tools/functions'; 3 | 4 | // Base 5 | @import 'base/variables'; 6 | @import 'base/base'; 7 | @import 'base/typography'; 8 | 9 | // Atoms 10 | @import 'atoms/buttons'; 11 | 12 | // Components 13 | @import 'components/header'; 14 | @import 'components/footer'; 15 | @import 'components/nav'; 16 | 17 | // Pages 18 | @import 'pages/home'; 19 | -------------------------------------------------------------------------------- /src/styles/pages/_home.scss: -------------------------------------------------------------------------------- 1 | // Page Home 2 | 3 | .home { 4 | main { 5 | padding: remy(48px) remy(24px); 6 | 7 | @media screen and (min-width: 961px) { 8 | margin: 0 auto; 9 | width: 100%; 10 | max-width: remy(960px); 11 | } 12 | } 13 | } 14 | 15 | .page__top { 16 | padding-top: remy(96px); 17 | padding-bottom: remy(96px); 18 | text-align: center; 19 | 20 | h1 { 21 | margin-bottom: remy(12px); 22 | font-size: remy(32px); 23 | line-height: 1.6; 24 | } 25 | 26 | .btn { 27 | margin-top: remy(12px); 28 | margin-right: auto; 29 | margin-left: auto; 30 | } 31 | } 32 | 33 | .boilerplate-logo { 34 | clear: both; 35 | display: block; 36 | flex: none; 37 | overflow: hidden; 38 | margin-bottom: remy(24px); 39 | width: 100%; 40 | height: remy(112px); 41 | background: url(bull-icon.svg); 42 | background-repeat: no-repeat; 43 | background-position: center; 44 | background-size: remy(112px); 45 | } 46 | 47 | .main__header { 48 | padding-bottom: 72px; 49 | width: 100%; 50 | color: #000; 51 | text-align: center; 52 | } 53 | 54 | hr { 55 | margin: 24px auto 0; 56 | max-width: 96px; 57 | height: 1px; 58 | color: #ddd; 59 | background-color: #ddd; 60 | border: none; 61 | } 62 | 63 | .main__content { 64 | display: flex; 65 | flex-wrap: wrap; 66 | justify-content: center; 67 | width: 100%; 68 | } 69 | 70 | .main__item { 71 | display: flex; 72 | flex: 0 1 auto; 73 | flex-flow: column nowrap; 74 | width: 100%; 75 | text-align: center; 76 | 77 | @media (min-width: 555px) { 78 | max-width: calc(50% - 48px); 79 | 80 | &:nth-of-type(2n+2) { 81 | margin-right: remy(48px); 82 | margin-left: remy(48px); 83 | } 84 | } 85 | 86 | @media (min-width: 555px) and (max-width: 991px) { 87 | &:nth-of-type(n+3) { 88 | margin-top: remy(48px); 89 | } 90 | } 91 | 92 | @media (min-width: 992px) { 93 | max-width: calc(33.33333% - 32px); 94 | 95 | &:nth-of-type(2) { 96 | margin-right: remy(48px); 97 | margin-left: remy(48px); 98 | } 99 | 100 | &:last-of-type { 101 | margin-top: remy(26px); 102 | } 103 | } 104 | 105 | h4 { 106 | margin-top: remy(16px); 107 | } 108 | } 109 | 110 | .main__item-logo { 111 | display: block; 112 | margin-right: auto; 113 | margin-left: auto; 114 | width: remy(48px); 115 | height: remy(48px); 116 | background: url(react-logo.png); 117 | background-repeat: no-repeat; 118 | background-size: contain; 119 | 120 | &.mobx { 121 | background: url(mobx-logo.png); 122 | background-repeat: no-repeat; 123 | background-size: contain; 124 | } 125 | 126 | &.reactrouter { 127 | background: url(react-router-logo.png); 128 | background-repeat: no-repeat; 129 | background-size: contain; 130 | } 131 | 132 | &.webpack { 133 | background: url(webpack-logo.png); 134 | background-repeat: no-repeat; 135 | background-size: contain; 136 | } 137 | } 138 | 139 | .main__extras { 140 | text-align: center; 141 | 142 | ul { 143 | padding: 0; 144 | margin: remy(24px) 0 0; 145 | list-style-type: none; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/styles/tools/_functions.scss: -------------------------------------------------------------------------------- 1 | // Functions 2 | 3 | // Convert pixels to rems 4 | @function remy($value, $base: 16px) { 5 | @return ($value / $base) * 1rem; 6 | } 7 | -------------------------------------------------------------------------------- /src/utils/constants.js: -------------------------------------------------------------------------------- 1 | const isProduction = process.env.NODE_ENV === 'production'; 2 | 3 | export { isProduction }; 4 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | 5 | module.exports = { 6 | entry: [ 7 | 'react-hot-loader/patch', 8 | 'webpack-dev-server/client?http://0.0.0.0:1337', 9 | 'webpack/hot/only-dev-server', 10 | 'babel-polyfill', 11 | 'whatwg-fetch', 12 | './src/index.js' 13 | ], 14 | devServer: { 15 | hot: true, 16 | contentBase: path.resolve(__dirname, 'dist'), 17 | port: process.env.PORT || 1337, 18 | host: '0.0.0.0', 19 | publicPath: '/', 20 | historyApiFallback: true, 21 | disableHostCheck: true 22 | }, 23 | output: { 24 | path: path.join(__dirname, 'dist'), 25 | publicPath: '/', 26 | filename: 'app.[hash].js' 27 | }, 28 | devtool: 'eval', 29 | module: { 30 | rules: [ 31 | { 32 | test: /\.js$/, 33 | exclude: /node_modules/, 34 | loader: 'babel-loader', 35 | options: { 36 | presets: [ 37 | [ 38 | 'es2015', 39 | { 40 | 'modules': false 41 | } 42 | ], 43 | 'stage-0', 44 | 'react' 45 | ], 46 | plugins: [ 47 | 'transform-async-to-generator', 48 | 'transform-decorators-legacy' 49 | ] 50 | } 51 | }, 52 | { 53 | test: /\.scss|css$/, 54 | use: [ 55 | 'style-loader', 56 | 'css-loader', 57 | 'postcss-loader', 58 | 'resolve-url-loader', 59 | 'sass-loader?sourceMap' 60 | ] 61 | }, 62 | { 63 | test: /\.(jpe?g|png|gif|svg)$/i, 64 | use: [ 65 | 'file-loader?hash=sha512&digest=hex&name=[hash].[ext]', 66 | { 67 | loader: 'image-webpack-loader', 68 | query: { 69 | mozjpeg: { 70 | progressive: true 71 | }, 72 | gifsicle: { 73 | interlaced: false 74 | }, 75 | optipng: { 76 | optimizationLevel: 4 77 | }, 78 | pngquant: { 79 | quality: '75-90', 80 | speed: 3 81 | } 82 | } 83 | } 84 | ] 85 | }, 86 | { 87 | test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, 88 | use: 'url-loader?limit=10000&mimetype=application/font-woff' 89 | }, 90 | { 91 | test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, 92 | use: 'file-loader', 93 | exclude: /images/, 94 | } 95 | ] 96 | }, 97 | plugins: [ 98 | new webpack.NamedModulesPlugin(), 99 | new webpack.HotModuleReplacementPlugin(), 100 | new HtmlWebpackPlugin({ hash: false, template: './index.hbs' }), 101 | new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /nb/) 102 | ] 103 | }; 104 | -------------------------------------------------------------------------------- /webpack.config.production.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 5 | 6 | module.exports = { 7 | entry: { 8 | vendor: ['react', 'react-dom', 'react-router'], 9 | app: ['babel-polyfill', './src/index.js'] 10 | }, 11 | output: { 12 | path: path.join(__dirname, 'dist'), 13 | publicPath: './', 14 | filename: 'assets/[name].[hash].js', 15 | chunkFilename: 'assets/[name].[chunkhash].js' 16 | }, 17 | devtool: 'cheap-module-source-map', 18 | module: { 19 | rules: [ 20 | { 21 | test: /\.js$/, 22 | include: path.join(__dirname, 'src'), 23 | loader: 'babel-loader', 24 | query: { 25 | presets: [ 26 | [ 27 | 'es2015', 28 | { 29 | modules: false 30 | } 31 | ], 32 | 'stage-0', 33 | 'react' 34 | ], 35 | plugins: [ 36 | 'transform-async-to-generator', 37 | 'transform-decorators-legacy' 38 | ] 39 | } 40 | }, 41 | { 42 | test: /\.scss|css$/i, 43 | use: [ 44 | MiniCssExtractPlugin.loader, 45 | { loader: 'css-loader', options: { sourceMap: true } }, 46 | { loader: 'postcss-loader', options: { sourceMap: true } }, 47 | { loader: 'resolve-url-loader' }, 48 | { loader: 'sass-loader', options: { sourceMap: true } } 49 | ] 50 | }, 51 | { 52 | test: /\.(jpe?g|png|gif|svg)$/i, 53 | use: [ 54 | 'file-loader?hash=sha512&digest=hex&name=[hash].[ext]', 55 | { 56 | loader: 'image-webpack-loader', 57 | query: { 58 | mozjpeg: { 59 | progressive: true 60 | }, 61 | gifsicle: { 62 | interlaced: false 63 | }, 64 | optipng: { 65 | optimizationLevel: 4 66 | }, 67 | pngquant: { 68 | quality: '75-90', 69 | speed: 3 70 | } 71 | } 72 | } 73 | ] 74 | }, 75 | { 76 | test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, 77 | use: 'url-loader?limit=10000&mimetype=application/font-woff' 78 | }, 79 | { 80 | test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, 81 | use: 'file-loader' 82 | } 83 | ] 84 | }, 85 | plugins: [ 86 | new webpack.DefinePlugin({ 87 | 'process.env': { 88 | NODE_ENV: JSON.stringify('production') 89 | } 90 | }), 91 | new webpack.NamedModulesPlugin(), 92 | new webpack.optimize.OccurrenceOrderPlugin(true), 93 | new MiniCssExtractPlugin({ 94 | // Options similar to the same options in webpackOptions.output 95 | // both options are optional 96 | filename: 'assets/styles.css', 97 | chunkFilename: '[id].css' 98 | }), 99 | new HtmlWebpackPlugin({ 100 | hash: false, 101 | template: './index.hbs' 102 | }) 103 | ] 104 | }; 105 | --------------------------------------------------------------------------------