├── .eslintrc ├── .gitignore ├── LICENCE.md ├── README.md ├── docs ├── .nojekyll ├── 0e021f12d426d36ff02a3e9001e29ec7.jpg ├── 12290a44ad51b2ff2c5edc8ef538e2dd.jpg ├── 1ea04a16928be0b78fd8f78d49107fb6.jpg ├── avatar.png ├── build.html ├── d69ae1e0d46bcf466774294e59378a37.jpg ├── err.html ├── index.html └── static │ ├── css │ ├── app.8f0b8c01.css │ └── app.8f0b8c01.css.map │ └── js │ ├── 0.9f0bc0a3.chunk.js │ ├── 0.9f0bc0a3.chunk.js.map │ ├── app.0e732cc4.js │ ├── app.0e732cc4.js.map │ ├── manifest.063c8024.js │ ├── manifest.063c8024.js.map │ ├── vendor.b4b3e991.js │ └── vendor.b4b3e991.js.map ├── example ├── .babelrc ├── .dockerignore ├── .eslintrc ├── Dockerfile ├── assets │ ├── avatar-favicon.sketch │ ├── avatar.sketch │ ├── images │ │ ├── 0.jpg │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ └── avatar.svg │ └── replays │ │ ├── build.txt │ │ └── err.txt ├── config │ ├── .webpack-records.json │ ├── babel.dev.js │ ├── babel.prod.js │ ├── paths.js │ ├── template │ │ ├── avatar.png │ │ └── index.html │ ├── webpack.config.dev.babel.js │ └── webpack.config.production.babel.js ├── package.json ├── server │ ├── index.js │ ├── package.json │ └── yarn.lock ├── src │ ├── App.js │ ├── Carusel.js │ ├── Container.js │ ├── Content.js │ ├── Layout.js │ ├── Replay.js │ ├── Term.js │ ├── __tests__ │ │ └── dev.js │ ├── carusel.sass │ ├── container.sass │ ├── content.sass │ ├── enhancers │ │ ├── AsyncMatch.js │ │ └── MatchWithProps.js │ ├── layout.sass │ ├── main.js │ ├── main.sass │ ├── reducer.js │ ├── replay.sass │ └── utils │ │ ├── colors.js │ │ ├── defaultConfig.js │ │ ├── hterm.js │ │ └── runes.js └── yarn.lock ├── ideas.md ├── lerna.json ├── package.json └── packages ├── pbl ├── README.md ├── index.js ├── lib │ └── cfg.js ├── package.json └── scripts │ └── run.sh ├── pbls ├── README.md ├── index.js ├── lib │ └── cfg.js ├── package.json └── scripts │ ├── clean.sh │ ├── install.sh │ └── run.sh ├── pty64 ├── README.md ├── index.js └── package.json └── stdind ├── .babelrc ├── .dockerignore ├── .eslintrc ├── Dockerfile ├── LICENSE-3RD-PARTY.md ├── README.md ├── config ├── babel.dev.js ├── babel.prod.js ├── paths.js ├── template │ ├── avatar.png │ └── index.html ├── webpack.config.dev.babel.js └── webpack.config.production.babel.js ├── example.gif ├── examples └── longRunning.js ├── images └── avatar.svg ├── package.json ├── server ├── index.js ├── package.json └── yarn.lock ├── src ├── App.js ├── Container.js ├── Layout.js ├── Term.js ├── __tests__ │ └── dev.js ├── container.sass ├── enhancers │ └── MatchWithProps.js ├── layout.sass ├── main.js ├── main.sass ├── reducer.js └── utils │ ├── colors.js │ ├── defaultConfig.js │ ├── hterm.js │ └── runes.js └── yarn.lock /.eslintrc: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "extends": "airbnb", 4 | "parser": "babel-eslint", 5 | "env": { 6 | "browser": true, 7 | "mocha": true, 8 | "node": true 9 | }, 10 | "rules": { 11 | "no-nested-ternary": 0, 12 | "react/prop-types": 0, 13 | "react/jsx-filename-extension": 0, 14 | "no-sequences": 1, 15 | "comma-dangle": 0, 16 | }, 17 | "globals": { 18 | "ReactElement": false 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules 3 | npm-debug.log 4 | lerna-debug.log 5 | -------------------------------------------------------------------------------- /LICENCE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pbl 2 | 3 | `pbl` gives users the ability to make fast and easy deployment of their Docker powered applications and services onto their server. 4 | Any directory that contains a Dockerfile can be deployed with just one command: `pbl`. 5 | 6 | Every time a user deploys a project, `pbl` (by default), will immediately 7 | provide a new unique URL. 8 | While the build process runs, a full-featured, view-only terminal with all the build 9 | process output will be available at the provided URL. 10 | 11 | If the build process is successful, the app itself will become available at the same URL, otherwise the terminal with the build process output and error(s) will remain available. 12 | 13 | ## Client install 14 | 15 | ### Prerequisites 16 | 17 | To make pbl work, nodejs needs to be installed on the client machine. 18 | 19 | ### Install 20 | 21 | ```bash 22 | npm install -g pbl 23 | pbl init --identity {SSH-IDENTITY-FILE-PATH} --server {USER@YOUR-SERVER-HOST-OR-IP} 24 | # example: pbl init --identity ~/.ssh/mykey.pem --server ubuntu@ui.revue.io 25 | ``` 26 | 27 | PS: For node projects, there is no need to setup `pbl` globally, 28 | and it can be installed into devDependencies of a project. 29 | 30 | ## Server install 31 | 32 | ### Prerequisites 33 | 34 | Docker + Node LTS + build-essential (make) + python, 35 | you need to own domain name (or just use `/etc/hosts`), 36 | and have a DNS record for third (in some cases fourth) level pointing to your server. 37 | 38 | I highly recommend you to use overlay2 for docker storage driver, because of this issue 39 | https://github.com/docker/docker/issues/10613 40 | 41 | ### Install 42 | 43 | ```bash 44 | npm install -g pbls 45 | pbls init --domain {YOUR DOMAIN} 46 | # example: pbls init --domain ui.revue.io 47 | # as I want to publish all content under fourth level domain 48 | ``` 49 | 50 | ## Usage Example 51 | 52 | Clone current project. 53 | 54 | Open `example` dir and run `pbl`, project will be published at `{rnd}.{YOUR DOMAIN}` host. 55 | 56 | Run `pbl --name hello` then the project will be published at `hello.{YOUR DOMAIN}` host. 57 | 58 | To use dockerfile with other name than `Dockerfile` just run as `pbl --dockerFile ./DockerfileOther` 59 | 60 | By default `pbl` runs deploys in detached mode, and exits almost immediately after running, 61 | but sometimes if you need more control you can run `pbl` in `attached` mode, 62 | just add `--attached true` 63 | 64 | To pass ARGs to Docker build, just append `--build-arg` like 65 | `pbl --name hello --build-arg PARAM=LALA` 66 | 67 | ## Server cleanup 68 | 69 | As most of the time all these containers are no longer needed after a few days, just add the following command into `cron`: 70 | 71 | ```bash 72 | pbls clean --days {X} 73 | ``` 74 | 75 | This command will stop all containers that were started before `current date` - `{X}` days, and will also clean all exited containers. 76 | 77 | For full cleanup run: 78 | 79 | ```bash 80 | pbls clean --days 0 81 | ``` 82 | 83 | ## Contribute 84 | 85 | To use locally: 86 | 87 | * `npm install` 88 | 89 | * add `127.0.0.1 *.localhost` to `/etc/hosts`, 90 | 91 | * initialize `pbls` by running it directly as `./packages/pbls/index.js init --domain localhost` 92 | 93 | * then `cd` `example` or any Dockerfile folder and run local pbl in dev mode like `../packages/pbl/index.js --mode dev` 94 | 95 | ## TODO 96 | 97 | Add running server output log to some path like `http://{NAME}.{YOUR DOMAIN}/logs` 98 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/0e021f12d426d36ff02a3e9001e29ec7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istarkov/pbl/525c604d53a64a00e969b2efb0b96f6ee96df6de/docs/0e021f12d426d36ff02a3e9001e29ec7.jpg -------------------------------------------------------------------------------- /docs/12290a44ad51b2ff2c5edc8ef538e2dd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istarkov/pbl/525c604d53a64a00e969b2efb0b96f6ee96df6de/docs/12290a44ad51b2ff2c5edc8ef538e2dd.jpg -------------------------------------------------------------------------------- /docs/1ea04a16928be0b78fd8f78d49107fb6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istarkov/pbl/525c604d53a64a00e969b2efb0b96f6ee96df6de/docs/1ea04a16928be0b78fd8f78d49107fb6.jpg -------------------------------------------------------------------------------- /docs/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istarkov/pbl/525c604d53a64a00e969b2efb0b96f6ee96df6de/docs/avatar.png -------------------------------------------------------------------------------- /docs/build.html: -------------------------------------------------------------------------------- 1 | index.html -------------------------------------------------------------------------------- /docs/d69ae1e0d46bcf466774294e59378a37.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istarkov/pbl/525c604d53a64a00e969b2efb0b96f6ee96df6de/docs/d69ae1e0d46bcf466774294e59378a37.jpg -------------------------------------------------------------------------------- /docs/err.html: -------------------------------------------------------------------------------- 1 | index.html -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | PBL
-------------------------------------------------------------------------------- /docs/static/css/app.8f0b8c01.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit;font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}[hidden],template{display:none}#app{min-height:100vh;display:-ms-flexbox;display:flex}body,html{font-size:16px;background-color:#272822;color:#f8f8f2;color:#ddd;font-family:Roboto;-webkit-font-smoothing:antialiased}body{visibility:hidden}.wf-active body,.wf-inactive body{visibility:visible}@media only screen and (max-width:700px){body,html{font-size:14px}}@media only screen and (max-width:550px){body,html{font-size:12px}}.container__component{display:-ms-flexbox;display:flex;-ms-flex:1;flex:1}.container__content{-ms-flex:6;flex:6;position:relative;display:-ms-flexbox;display:flex}.container__contentAside{-ms-flex:1;flex:1;min-width:80px}@media only screen and (max-width:700px){.container__content{-ms-flex:10;flex:10}.container__contentAside{min-width:20px}}.carusel__main{display:-ms-flexbox;display:flex;-ms-flex:1;flex:1;-ms-flex-pack:distribute;justify-content:space-around;-ms-flex-align:center;align-items:center}.carusel__holder{-ms-flex:1;flex:1}.carusel__card{position:relative}.carusel__card:before{display:block;width:100%;padding-top:75%;content:""}.carusel__card>.carusel__aspectRatioContent{position:absolute;top:0;left:0;width:100%;height:100%}.carusel__card.slick-center{z-index:100}.carusel__card.slick-center .carusel__innerCard{border:1px solid #fff}.carusel__aspectRatioContent,.carusel__innerCard{display:-ms-flexbox;display:flex}.carusel__innerCard{background-size:cover;margin:3px;border:1px solid transparent;-ms-flex:1;flex:1;background-color:#272822}.carusel__description{-ms-flex:1;flex:1;min-height:32px;text-shadow:1px 1px 1px rgba(0,0,0,.8);font-size:14px;margin:auto 5px 5px;padding:5px;background-color:rgba(0,0,0,.7)}.content__main{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-height:500px}.content__main A,.content__main H1,.content__main STRONG{color:#20beff;text-decoration:none}.content__main P:last-child{text-align:right}.content__data{-ms-flex:1;flex:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.content__link{text-decoration:none}*{min-width:0;min-height:0}.layout__component{-ms-flex:1;flex:1;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.layout__header{border-bottom:1px solid #666;background-color:rgba(0,0,0,.05);display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;color:#999}.layout__header A,.layout__header H1{color:#20beff;text-decoration:none}.layout__header SPAN{font-size:10px;margin-left:4px}@media only screen and (max-width:550px){.layout__header SPAN{display:none}}.layout__header .layout__headerMenu A{font-size:14px;margin-left:6px}.layout__header .layout__headerMenu A+A{margin-left:6px}.layout__header .layout__headerContent{-ms-flex-pack:justify;justify-content:space-between;-ms-flex-align:baseline;align-items:baseline}.layout__header .layout__headerLeft{display:-ms-flexbox;display:flex;-ms-flex-align:baseline;align-items:baseline}.layout__header .layout__headerLeft .layout__headerText{margin:10px 0}.layout__loading{margin:auto}.layout__footer{font-size:.8rem;height:2rem;border-top:1px solid hsla(0,0%,100%,.1);background-color:rgba(0,0,0,.05);display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.layout__footer .layout__footerContent{-ms-flex-pack:end;justify-content:flex-end;-ms-flex-align:baseline;align-items:baseline}.layout__team{color:#999;font-size:10px}.layout__avatarLine{height:0;position:relative;pointer-events:none}.layout__avatarHolder{position:absolute;left:0;right:0;display:-ms-flexbox;display:flex;top:-41px;z-index:1}.layout__avatar{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMTUycHgiIGhlaWdodD0iNjZweCIgdmlld0JveD0iMCAwIDE1MiA2NiIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KICAgIDwhLS0gR2VuZXJhdG9yOiBTa2V0Y2ggNDEuMiAoMzUzOTcpIC0gaHR0cDovL3d3dy5ib2hlbWlhbmNvZGluZy5jb20vc2tldGNoIC0tPgogICAgPHRpdGxlPmF2YXRhcjwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxkZWZzPgogICAgICAgIDxwYXRoIGQ9Ik01OS40NjQ4NTg1LDIyLjkxOTE0ODYgQzU5LjQ2NDg1ODUsMjIuOTE5MTQ4NiA3Mi45NjQ4NTg1LDUxLjEyOTM1MTUgNTkuNDY0ODU4NSw2MC41MzI3NTI1IEM0NS45NjQ4NTg1LDY5LjkzNjE1MzUgNi4zODA5MTM3LDYwLjc2MTAyNDcgNi4zODA5MTM3LDYwLjc2MTAyNDcgQzYuMzgwOTEzNyw2MC43NjEwMjQ3IDMyLjM5MjgxOTMsNTQuODAxODAwOCA0Mi4zMzAwOTI4LDQ3Ljg4MDAxMDYgQzUyLjI2NzM2NjQsNDAuOTU4MjIwNCA1OS40NjQ4NTg1LDIyLjkxOTE0ODYgNTkuNDY0ODU4NSwyMi45MTkxNDg2IFoiIGlkPSJwYXRoLTEiPjwvcGF0aD4KICAgICAgICA8bWFzayBpZD0ibWFzay0yIiBtYXNrQ29udGVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFza1VuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeD0iMCIgeT0iMCIgd2lkdGg9IjU5LjA4Mzk0NDgiIGhlaWdodD0iNDEuODUyOTA3MSIgZmlsbD0id2hpdGUiPgogICAgICAgICAgICA8dXNlIHhsaW5rOmhyZWY9IiNwYXRoLTEiPjwvdXNlPgogICAgICAgIDwvbWFzaz4KICAgICAgICA8cGF0aCBkPSJNMTM5LjY2NDI3MiwyMi4yOTUxMDkzIEMxMzkuNjY0MjcyLDIyLjI5NTEwOTMgMTUzLjE2NDI3Miw1MC41MDUzMTIyIDEzOS42NjQyNzIsNTkuOTA4NzEzMiBDMTI2LjE2NDI3Miw2OS4zMTIxMTQyIDg1LjQ5MjcwMDIsNTkuNTQwNzc2MiA4NS40OTI3MDAyLDU5LjU0MDc3NjIgQzg1LjQ5MjcwMDIsNTkuNTQwNzc2MiAxMTIuNTkyMjMzLDU0LjE3Nzc2MTQgMTIyLjUyOTUwNiw0Ny4yNTU5NzEzIEMxMzIuNDY2NzgsNDAuMzM0MTgxMSAxMzkuNjY0MjcyLDIyLjI5NTEwOTMgMTM5LjY2NDI3MiwyMi4yOTUxMDkzIFoiIGlkPSJwYXRoLTMiPjwvcGF0aD4KICAgICAgICA8bWFzayBpZD0ibWFzay00IiBtYXNrQ29udGVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFza1VuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeD0iMCIgeT0iMCIgd2lkdGg9IjYwLjE3MTU3MTgiIGhlaWdodD0iNDEuNjk5NTg5NiIgZmlsbD0id2hpdGUiPgogICAgICAgICAgICA8dXNlIHhsaW5rOmhyZWY9IiNwYXRoLTMiPjwvdXNlPgogICAgICAgIDwvbWFzaz4KICAgICAgICA8cG9seWdvbiBpZD0icGF0aC01IiBwb2ludHM9IjguNjU0NDAyNzUgMjMuNTc1ODgyNiAxOS44NzY2MzYxIDE5LjkwNjk2MzcgMjMuOTI0NDc2OSAzMy4yNDUxNjE0IDE4LjI3NDE4MjcgMzguODk1NDU1NiA0LjY2MzAzODE3IDM0LjEzMDA1MTIiPjwvcG9seWdvbj4KICAgICAgICA8bWFzayBpZD0ibWFzay02IiBtYXNrQ29udGVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFza1VuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeD0iMCIgeT0iMCIgd2lkdGg9IjE5LjI2MTQzODciIGhlaWdodD0iMTguOTg4NDkxOSIgZmlsbD0id2hpdGUiPgogICAgICAgICAgICA8dXNlIHhsaW5rOmhyZWY9IiNwYXRoLTUiPjwvdXNlPgogICAgICAgIDwvbWFzaz4KICAgIDwvZGVmcz4KICAgIDxnIGlkPSJQYWdlLTEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxwYXRoIGQ9Ik0wLDM3Ljc2NTE4NTkgQzAsMzcuNzY1MTg1OSA0OS4wODg3NjMyLDM3IDc0LDM3IEM5OC45MTEyMzY4LDM3IDE1MSwzNy42OTQ2MjQ0IDE1MSwzNy42OTQ2MjQ0IEwxNTEsNDIuMTM5OTk5OSBMMCw0Mi4xMzk5OTk5IEwwLDM3Ljc2NTE4NTkgWiIgaWQ9IlJlY3RhbmdsZSIgZmlsbD0iIzI3MjgyMiI+PC9wYXRoPgogICAgICAgIDx1c2UgaWQ9IlJlY3RhbmdsZS00IiBzdHJva2U9IiM5OTkiIG1hc2s9InVybCgjbWFzay0yKSIgc3Ryb2tlLXdpZHRoPSIyIiBmaWxsPSIjMjcyODIyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzNS45MjI4ODYsIDQzLjg0NTYwMikgc2NhbGUoMSwgLTEpIHJvdGF0ZSgyNS4wMDAwMDApIHRyYW5zbGF0ZSgtMzUuOTIyODg2LCAtNDMuODQ1NjAyKSAiIHhsaW5rOmhyZWY9IiNwYXRoLTEiPjwvdXNlPgogICAgICAgIDx1c2UgaWQ9IlJlY3RhbmdsZS00IiBzdHJva2U9IiM5OTkiIG1hc2s9InVybCgjbWFzay00KSIgc3Ryb2tlLXdpZHRoPSIyIiBmaWxsPSIjMjcyODIyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMTUuNTc4NDg2LCA0My4xNDQ5MDQpIHNjYWxlKC0xLCAtMSkgcm90YXRlKDI1LjAwMDAwMCkgdHJhbnNsYXRlKC0xMTUuNTc4NDg2LCAtNDMuMTQ0OTA0KSAiIHhsaW5rOmhyZWY9IiNwYXRoLTMiPjwvdXNlPgogICAgICAgIDxyZWN0IGlkPSJSZWN0YW5nbGUtMyIgZmlsbD0iIzk5OSIgeD0iNTkiIHk9IjYxIiB3aWR0aD0iMTMiIGhlaWdodD0iMSI+PC9yZWN0PgogICAgICAgIDxyZWN0IGlkPSJSZWN0YW5nbGUtMyIgZmlsbD0iIzk5OSIgeD0iNzkiIHk9IjYxIiB3aWR0aD0iMTMiIGhlaWdodD0iMSI+PC9yZWN0PgogICAgICAgIDxwYXRoIGQ9Ik02NS41LDUxLjUgTDY1LjUsNjEuNSIgaWQ9IkxpbmUiIHN0cm9rZT0iIzk5OSIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSI+PC9wYXRoPgogICAgICAgIDxwYXRoIGQ9Ik04NS41LDUwLjUgTDg1LjUsNjAuNSIgaWQ9IkxpbmUiIHN0cm9rZT0iIzk5OSIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSI+PC9wYXRoPgogICAgICAgIDxnIGlkPSJHcm91cC0yIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg2MS4wMDAwMDAsIDMuMDAwMDAwKSI+CiAgICAgICAgICAgIDxlbGxpcHNlIGlkPSJPdmFsIiBzdHJva2U9IiM5OTkiIGZpbGw9IiMyNzI4MjIiIGN4PSIxNSIgY3k9IjE1IiByeD0iMTUiIHJ5PSIxNSI+PC9lbGxpcHNlPgogICAgICAgICAgICA8dXNlIGlkPSJSZWN0YW5nbGUtMiIgc3Ryb2tlPSIjOTk5IiBtYXNrPSJ1cmwoI21hc2stNikiIHN0cm9rZS13aWR0aD0iMiIgZmlsbD0iIzI3MjgyMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTQuMjkzNzU4LCAyOS40MDEyMTApIHJvdGF0ZSg0NS4wMDAwMDApIHRyYW5zbGF0ZSgtMTQuMjkzNzU4LCAtMjkuNDAxMjEwKSAiIHhsaW5rOmhyZWY9IiNwYXRoLTUiPjwvdXNlPgogICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0yIiBzdHJva2U9IiM5OTkiIGN4PSI3LjUiIGN5PSIxMy43NSIgcng9IjMuNzUiIHJ5PSIzLjc1Ij48L2VsbGlwc2U+CiAgICAgICAgICAgIDxjaXJjbGUgaWQ9Ik92YWwtMiIgc3Ryb2tlPSIjOTk5IiBjeD0iMjEuMjUiIGN5PSIxMy43NSIgcj0iMy43NSI+PC9jaXJjbGU+CiAgICAgICAgICAgIDxlbGxpcHNlIGlkPSJPdmFsLTMiIGZpbGw9IiM5OTkiIGN4PSI3LjUiIGN5PSIxMy43NSIgcng9IjEuMjUiIHJ5PSIxLjI1Ij48L2VsbGlwc2U+CiAgICAgICAgICAgIDxjaXJjbGUgaWQ9Ik92YWwtMyIgZmlsbD0iIzk5OSIgY3g9IjIxLjI1IiBjeT0iMTMuNzUiIHI9IjEuMjUiPjwvY2lyY2xlPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+Cg==);background-size:contain;background-repeat:no-repeat;height:66px;width:150px;margin:0 auto} 2 | /*# sourceMappingURL=app.8f0b8c01.css.map*/ -------------------------------------------------------------------------------- /docs/static/css/app.8f0b8c01.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"static/css/app.8f0b8c01.css","sourceRoot":""} -------------------------------------------------------------------------------- /docs/static/js/manifest.063c8024.js: -------------------------------------------------------------------------------- 1 | !function(e){function t(n){if(c[n])return c[n].exports;var a=c[n]={exports:{},id:n,loaded:!1};return e[n].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var n=window.webpackJsonp;window.webpackJsonp=function(r,o){for(var i,p,s=0,l=[];s/dev/null && \ 34 | pty64 -- yarn run lint && \ 35 | pty64 -- yarn run build && \ 36 | rm -rf ./node_modules 37 | 38 | CMD /usr/local/bin/dumb-init -- node ./server/index.js 39 | -------------------------------------------------------------------------------- /example/assets/avatar-favicon.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istarkov/pbl/525c604d53a64a00e969b2efb0b96f6ee96df6de/example/assets/avatar-favicon.sketch -------------------------------------------------------------------------------- /example/assets/avatar.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istarkov/pbl/525c604d53a64a00e969b2efb0b96f6ee96df6de/example/assets/avatar.sketch -------------------------------------------------------------------------------- /example/assets/images/0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istarkov/pbl/525c604d53a64a00e969b2efb0b96f6ee96df6de/example/assets/images/0.jpg -------------------------------------------------------------------------------- /example/assets/images/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istarkov/pbl/525c604d53a64a00e969b2efb0b96f6ee96df6de/example/assets/images/1.jpg -------------------------------------------------------------------------------- /example/assets/images/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istarkov/pbl/525c604d53a64a00e969b2efb0b96f6ee96df6de/example/assets/images/2.jpg -------------------------------------------------------------------------------- /example/assets/images/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istarkov/pbl/525c604d53a64a00e969b2efb0b96f6ee96df6de/example/assets/images/3.jpg -------------------------------------------------------------------------------- /example/assets/images/avatar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | avatar 5 | Created with Sketch. 6 | 7 | 8 | 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 | -------------------------------------------------------------------------------- /example/assets/replays/err.txt: -------------------------------------------------------------------------------- 1 | U2VuZGluZyBidWlsZCBjb250ZXh0IHRvIERvY2tlciBkYWVtb24gNTU3LjEga0IN 2 | U2VuZGluZyBidWlsZCBjb250ZXh0IHRvIERvY2tlciBkYWVtb24gICA3NDUga0INDQ0K 3 | U3RlcCAxLzE0IDogRlJPTSBub2RlOjYuOS4yLWFscGluZQ0K 4 | IC0tLT4gZGU1Mjk4NDVjMTExDQpTdGVwIDIvMTQgOiBSVU4gYXBrIGFkZCAtLW5vLWNhY2hlIG9wZW5zc2wgcHl0aG9uIGJ1aWxkLWJhc2UgJiYgd2dldCAtTyAvdXNyL2xvY2FsL2Jpbi9kdW1iLWluaXQgaHR0cHM6Ly9naXRodWIuY29tL1llbHAvZHVtYi1pbml0L3JlbGVhc2VzL2Rvd25sb2FkL3YxLjEuMi9kdW1iLWluaXRfMS4xLjJfYW1kNjQgJiYgY2htb2QgK3ggL3Vzci9sb2NhbC9iaW4vZHVtYi1pbml0ICYmIGFwayBkZWwgb3BlbnNzbA0K 5 | IC0tLT4gVXNpbmcgY2FjaGUNCg== 6 | IC0tLT4gODI2MzQ2NmYwODM2DQo= 7 | U3RlcCAzLzE0IDogRVhQT1NFIDQwMDANCg== 8 | IC0tLT4gVXNpbmcgY2FjaGUNCiAtLS0+IDg0YmU2Mjk3NmZmMg0K 9 | U3RlcCA0LzE0IDogV09SS0RJUiAvYXBwDQo= 10 | IC0tLT4gVXNpbmcgY2FjaGUNCg== 11 | IC0tLT4gNzA3ZmQ4MzBhOTkxDQpTdGVwIDUvMTQgOiBSVU4gbnBtIGluc3RhbGwgLS1sb2dsZXZlbCBlcnJvciAtLWdsb2JhbCB5YXJuIHB0eTY0DQo= 12 | IC0tLT4gVXNpbmcgY2FjaGUNCiAtLS0+IDcwNzU2NjJmNjhkMA0K 13 | U3RlcCA2LzE0IDogQUREIC4vcGFja2FnZS5qc29uIC4vDQo= 14 | IC0tLT4gVXNpbmcgY2FjaGUNCg== 15 | IC0tLT4gODE5NjMwNDM4YTZiDQpTdGVwIDcvMTQgOiBBREQgLi95YXJuLmxvY2sgLi8NCg== 16 | IC0tLT4gVXNpbmcgY2FjaGUNCg== 17 | IC0tLT4gYTk5ZjQ0NWRlZWQ4DQpTdGVwIDgvMTQgOiBBREQgLi9zZXJ2ZXIvcGFja2FnZS5qc29uIC4vc2VydmVyL3BhY2thZ2UuanNvbg0K 18 | IC0tLT4gVXNpbmcgY2FjaGUNCg== 19 | IC0tLT4gN2Y0NWQ5ZmQ0MWJiDQo= 20 | U3RlcCA5LzE0IDogQUREIC4vc2VydmVyL3lhcm4ubG9jayAuL3NlcnZlci95YXJuLmxvY2sNCg== 21 | IC0tLT4gVXNpbmcgY2FjaGUNCg== 22 | IC0tLT4gZTE2NzlhMDE3NzFkDQpTdGVwIDEwLzE0IDogUlVOIGNkIHNlcnZlciAmJiB5YXJuICYmIGNkIC4uICYmIHB0eTY0IC0tIHlhcm4gJiYgdGFyIC1jemYgL3RtcC9hcHAudGFyLmd6IC4gJiYgeWFybiBjYWNoZSBjbGVhbiAmJiBybSAtcmYgLi8qIC9yb290Ly5ucG0gL3Jvb3QvLm5vZGUtZ3lwIC9yb290Ly5nbnVwZw0K 23 | IC0tLT4gVXNpbmcgY2FjaGUNCg== 24 | IC0tLT4gNWZjNWZhMWMyNzg2DQpTdGVwIDExLzE0IDogQUREIC4gLi8NCg== 25 | IC0tLT4gZTY0OWIyZTQzOTgzDQo= 26 | UmVtb3ZpbmcgaW50ZXJtZWRpYXRlIGNvbnRhaW5lciAwZjgzMWQ3NGY3NGENCg== 27 | U3RlcCAxMi8xNCA6IFJVTiB0YXIgLXp4dmYgL3RtcC9hcHAudGFyLmd6IDE+L2Rldi9udWxsICYmIHB0eTY0IC0tIHlhcm4gcnVuIGxpbnQgJiYgcHR5NjQgLS0geWFybiBydW4gYnVpbGQgJiYgcm0gLXJmIC4vbm9kZV9tb2R1bGVzDQo= 28 | IC0tLT4gUnVubmluZyBpbiBhMmY5N2ZmN2RjNjYNCg== 29 | G1sySw== 30 | G1sxRxtbMW15YXJuIHJ1biB2MC4xOC4xG1syMm0NDQo= 31 | G1sySxtbMUcbWzJtJCBlc2xpbnQgc3JjIBtbMjJtDQ0K 32 | DQ0KG1s0bS9hcHAvc3JjL0FwcC5qcxtbMjRtDQ0KICAbWzJtMzoyMBtbMjJtICAbWzMxbWVycm9yG1szOW0gIFBhcnNlIGVycm9ycyBpbiBpbXBvcnRlZCBtb2R1bGUgJy4vTGF5b3V0JzogTGluZSA3MDogVW5leHBlY3RlZCB0b2tlbiwgZXhwZWN0ZWQgLA0NCg0NChtbMG0gG1s5MG0gNjggfCAbWzM5bQ0NCiAbWzkwbSA2OSB8IBtbMzltG1szNm1leHBvcnQbWzM5bSAbWzM2bWNvbnN0G1szOW0gbGF5b3V0SE9DIBtbMzNtPRtbMzltIGNvbXBvc2UoDQ0KG1szMW0bWzFtPhtbMjJtG1szOW0bWzkwbSA3MCB8IBtbMzltICB0aGUgbXIoG1szMm0nbGF5b3V0JxtbMzltG1szM20sG1szOW0gbGF5b3V0U3R5bGVzKRtbMzNtLBtbMzltDQ0KIBtbOTBtICAgIHwgG1szOW0gICAgICAbWzMxbRtbMW1eG1syMm0bWzM5bQ0NCiAbWzkwbSA3MSB8IBtbMzltKRtbMzNtOxtbMzltDQ0KIBtbOTBtIDcyIHwgG1szOW0NDQogG1s5MG0gNzMgfCAbWzM5bRtbMzZtZXhwb3J0G1szOW0gG1szNm1kZWZhdWx0G1szOW0gbGF5b3V0SE9DKGxheW91dENvbXBvbmVudCkbWzMzbTsbWzM5bRtbMG0gKDcwOjcpICAbWzJtaW1wb3J0L25vLW5hbWVkLWFzLWRlZmF1bHQbWzIybQ0NCiAgG1sybTM6MjAbWzIybSAgG1szMW1lcnJvchtbMzltICBQYXJzZSBlcnJvcnMgaW4gaW1wb3J0ZWQgbW9kdWxlICcuL0xheW91dCc6IExpbmUgNzA6IFVuZXhwZWN0ZWQgdG9rZW4sIGV4cGVjdGVkICwNDQoNDQobWzBtIBtbOTBtIDY4IHwgG1szOW0NDQogG1s5MG0gNjkgfCAbWzM5bRtbMzZtZXhwb3J0G1szOW0gG1szNm1jb25zdBtbMzltIGxheW91dEhPQyAbWzMzbT0bWzM5bSBjb21wb3NlKA0NChtbMzFtG1sxbT4bWzIybRtbMzltG1s5MG0gNzAgfCAbWzM5bSAgdGhlIG1yKBtbMzJtJ2xheW91dCcbWzM5bRtbMzNtLBtbMzltIGxheW91dFN0eWxlcykbWzMzbSwbWzM5bQ0NCiAbWzkwbSAgICB8IBtbMzltICAgICAgG1szMW0bWzFtXhtbMjJtG1szOW0NDQogG1s5MG0gNzEgfCAbWzM5bSkbWzMzbTsbWzM5bQ0NCiAbWzkwbSA3MiB8IBtbMzltDQ== 33 | DQogG1s5MG0gNzMgfCAbWzM5bRtbMzZtZXhwb3J0G1szOW0gG1szNm1kZWZhdWx0G1szOW0gbGF5b3V0SE9DKGxheW91dENvbXBvbmVudCkbWzMzbTsbWzM5bRtbMG0gKDcwOjcpICAbWzJtaW1wb3J0L25vLW5hbWVkLWFzLWRlZmF1bHQtbWVtYmVyG1syMm0NDQoNDQobWzRtL2FwcC9zcmMvTGF5b3V0LmpzG1syNG0NDQogIBtbMm03MDo3G1syMm0gIBtbMzFtZXJyb3IbWzM5bSAgUGFyc2luZyBlcnJvcjogVW5leHBlY3RlZCB0b2tlbiwgZXhwZWN0ZWQgLA0NCg0NChtbMG0gG1s5MG0gNjggfCAbWzM5bQ0NCiAbWzkwbSA2OSB8IBtbMzltG1szNm1leHBvcnQbWzM5bSAbWzM2bWNvbnN0G1szOW0gbGF5b3V0SE9DIBtbMzNtPRtbMzltIGNvbXBvc2UoDQ0KG1szMW0bWzFtPhtbMjJtG1szOW0bWzkwbSA3MCB8IBtbMzltICB0aGUgbXIoG1szMm0nbGF5b3V0JxtbMzltG1szM20sG1szOW0gbGF5b3V0U3R5bGVzKRtbMzNtLBtbMzltDQ0KIBtbOTBtICAgIHwgG1szOW0gICAgICAbWzMxbRtbMW1eG1syMm0bWzM5bQ0NCiAbWzkwbSA3MSB8IBtbMzltKRtbMzNtOxtbMzltDQ0KIBtbOTBtIDcyIHwgG1szOW0NDQogG1s5MG0gNzMgfCAbWzM5bRtbMzZtZXhwb3J0G1szOW0gG1szNm1kZWZhdWx0G1szOW0gbGF5b3V0SE9DKGxheW91dENvbXBvbmVudCkbWzMzbTsbWzM5bRtbMG0NDQoNDQobWzMxbRtbMW3inJYgMyBwcm9ibGVtcyAoMyBlcnJvcnMsIDAgd2FybmluZ3MpDQ0KG1syMm0bWzM5bQ0NCg== 34 | G1sySxtbMUcbWzMxbWVycm9yG1szOW0gQ29tbWFuZCBmYWlsZWQgd2l0aCBleGl0IGNvZGUgMS4NDQo= 35 | G1sySxtbMUcbWzM0bWluZm8bWzM5bSBWaXNpdCAbWzFtaHR0cHM6Ly95YXJucGtnLmNvbS9lbi9kb2NzL2NsaS9ydW4bWzIybSBmb3IgZG9jdW1lbnRhdGlvbiBhYm91dCB0aGlzIGNvbW1hbmQuDQ0K 36 | VGhlIGNvbW1hbmQgJy9iaW4vc2ggLWMgdGFyIC16eHZmIC90bXAvYXBwLnRhci5neiAxPi9kZXYvbnVsbCAmJiBwdHk2NCAtLSB5YXJuIHJ1biBsaW50ICYmIHB0eTY0IC0tIHlhcm4gcnVuIGJ1aWxkICYmIHJtIC1yZiAuL25vZGVfbW9kdWxlcycgcmV0dXJuZWQgYSBub24temVybyBjb2RlOiAxDQo= 37 | -------------------------------------------------------------------------------- /example/config/babel.dev.js: -------------------------------------------------------------------------------- 1 | export default { 2 | babelrc: false, 3 | cacheDirectory: true, 4 | presets: [ 5 | 'babel-preset-latest', 6 | 'babel-preset-react', 7 | 'babel-preset-stage-0', 8 | ].map(require.resolve), 9 | 10 | plugins: [ 11 | 'markdown-in-js/babel', 12 | 'react-hot-loader/babel', 13 | // 'babel-plugin-transform-decorators-legacy', 14 | ].map(require.resolve) 15 | .concat([ 16 | [ 17 | require.resolve('babel-plugin-transform-runtime'), 18 | { 19 | helpers: false, 20 | polyfill: false, 21 | regenerator: true, 22 | }, 23 | ], 24 | ]), 25 | }; 26 | -------------------------------------------------------------------------------- /example/config/babel.prod.js: -------------------------------------------------------------------------------- 1 | export default { 2 | babelrc: false, 3 | presets: [ 4 | 'babel-preset-es2015', 5 | 'babel-preset-es2016', 6 | 'babel-preset-react', 7 | 'babel-preset-stage-0', 8 | ].map(require.resolve), 9 | 10 | plugins: [ 11 | 'markdown-in-js/babel', 12 | ].map(require.resolve) 13 | .concat([[ 14 | require.resolve('babel-plugin-transform-runtime'), 15 | { 16 | helpers: false, 17 | polyfill: false, 18 | regenerator: true, 19 | }, 20 | ]]), 21 | }; 22 | -------------------------------------------------------------------------------- /example/config/paths.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | 3 | const BACKEND_URL = 'ws://localhost:4000'; // 'https://localhost'; 4 | 5 | export default { 6 | appBuild: path.join(__dirname, '../build'), 7 | appHtml: path.join(__dirname, './template/index.html'), 8 | appFavicon: path.join(__dirname, './template/avatar.png'), 9 | appSrc: path.join(__dirname, '../src'), 10 | appProxy: BACKEND_URL, 11 | appNodeModules: path.join(__dirname, '../node_modules'), 12 | }; 13 | -------------------------------------------------------------------------------- /example/config/template/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istarkov/pbl/525c604d53a64a00e969b2efb0b96f6ee96df6de/example/config/template/avatar.png -------------------------------------------------------------------------------- /example/config/template/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | PBL 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /example/config/webpack.config.dev.babel.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-extraneous-dependencies */ 2 | // New webpack config for cnr-frontend 3 | // TODO production config https://github.com/facebookincubator/create-react-app/blob/master/config/webpack.config.prod.js 4 | import path from 'path'; 5 | import autoprefixer from 'autoprefixer'; 6 | import webpack from 'webpack'; 7 | import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin'; 8 | import HtmlWebpackPlugin from 'html-webpack-plugin'; 9 | import babelConfig from './babel.dev'; 10 | import paths from './paths'; 11 | 12 | // remove all of this when we move project onto babel 6 13 | export default { 14 | devtool: 'cheap-source-map', 15 | entry: [ 16 | `${require.resolve('webpack-dev-server/client')}?/`, 17 | require.resolve('webpack/hot/dev-server'), 18 | require.resolve('react-hot-loader/patch'), 19 | // path.join(paths.appSrc, 'polyfills'), 20 | path.join(paths.appSrc, 'main'), 21 | ], 22 | output: { 23 | // Next line is not used in dev but WebpackDevServer crashes without it: 24 | path: paths.appBuild, 25 | pathinfo: true, 26 | filename: 'static/js/bundle.js', 27 | publicPath: '/', 28 | }, 29 | devServer: { 30 | progress: true, 31 | colors: true, 32 | host: '0.0.0.0', 33 | port: (process.env.PORT || 3000), 34 | inline: true, 35 | hot: true, 36 | historyApiFallback: true, 37 | proxy: { 38 | // ws proxy 39 | ...( 40 | ['/ws/*'].reduce( 41 | (r, v) => ({ 42 | ...r, 43 | [v]: { 44 | target: paths.appProxy, 45 | ws: true, 46 | }, 47 | }), 48 | {}, 49 | ) 50 | ), 51 | }, 52 | }, 53 | resolve: { 54 | alias: { 55 | // 'react-components-markdown': path.join(__dirname, '../src'), 56 | }, 57 | modulesDirectories: [ 58 | paths.appSrc, 59 | 'node_modules', 60 | ], 61 | extensions: ['', '.web.js', '.js', '.jsx'], // eslint-disable-line 62 | }, 63 | resolveLoader: { 64 | root: paths.appNodeModules, 65 | }, 66 | postcss: [ 67 | autoprefixer({ browsers: ['last 2 versions'] }), 68 | ], 69 | plugins: [ 70 | new webpack.HotModuleReplacementPlugin(), 71 | new webpack.NoErrorsPlugin(), 72 | new HtmlWebpackPlugin({ 73 | inject: true, 74 | template: paths.appHtml, 75 | favicon: paths.appFavicon, 76 | }), 77 | // new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.bundle.js'), 78 | new webpack.DefinePlugin({ 79 | 'process.env': { 80 | NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development'), 81 | }, 82 | }), 83 | new CaseSensitivePathsPlugin(), 84 | ], 85 | module: { 86 | loaders: [ 87 | { 88 | test: /\.jsx?$/, 89 | loader: require.resolve('babel-loader'), 90 | query: babelConfig, 91 | include: [ 92 | paths.appSrc, 93 | ], 94 | }, 95 | { 96 | test: /\.sass$/, 97 | loaders: [ 98 | 'style-loader', 99 | 'css-loader?modules&importLoaders=2&localIdentName=[name]__[local]', // [hash:5] 100 | 'postcss-loader', 101 | 'sass-loader?precision=10&indentedSyntax=sass', 102 | ], 103 | include: [ 104 | paths.appSrc, 105 | ], 106 | }, 107 | { 108 | test: /\.css$/, 109 | loaders: [ 110 | 'style-loader', 111 | 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]', // [hash:5] 112 | 'postcss-loader', 113 | ], 114 | include: [ 115 | paths.appSrc, 116 | paths.appNodeModules, 117 | ], 118 | exclude: [ 119 | path.join(paths.appNodeModules, 'react-virtualized'), 120 | path.join(paths.appNodeModules, 'slick-carousel'), 121 | ], 122 | }, 123 | { 124 | test: /\.css$/, 125 | loaders: [ 126 | 'style-loader', 127 | 'css-loader', // [hash:5] 128 | 'postcss-loader', 129 | ], 130 | include: [ 131 | path.join(paths.appNodeModules, 'react-virtualized'), 132 | path.join(paths.appNodeModules, 'slick-carousel'), 133 | ], 134 | }, 135 | { 136 | test: /\.(?:svg|png|jpg)$/, 137 | loaders: ['url-loader?limit=7000'], 138 | }, 139 | { 140 | test: /\.(?:txt)$/, 141 | loaders: ['raw-loader'], 142 | } 143 | ], 144 | }, 145 | }; 146 | -------------------------------------------------------------------------------- /example/config/webpack.config.production.babel.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-len, import/no-extraneous-dependencies */ 2 | import path from 'path'; 3 | import autoprefixer from 'autoprefixer'; 4 | import webpack from 'webpack'; 5 | import HtmlWebpackPlugin from 'html-webpack-plugin'; 6 | import ExtractTextPlugin from 'extract-text-webpack-plugin'; 7 | import babelConfig from './babel.prod'; 8 | import paths from './paths'; 9 | 10 | // Development builds of React are slow and not intended for production. 11 | if (process.env.NODE_ENV !== 'production') { 12 | throw new Error('Production builds must have NODE_ENV=production.'); 13 | } 14 | 15 | const publicPath = process.env.BUILD ? '/pbl/' : '/'; 16 | 17 | const envObj = Object.keys(process.env) 18 | .reduce((r, k) => ({ 19 | ...r, 20 | [k]: JSON.stringify(process.env[k]), 21 | }), { 22 | NODE_ENV: '"development"', 23 | }); 24 | 25 | // remove all of this when we move project onto babel 6 26 | export default { 27 | // Don't attempt to continue if there are any errors. 28 | bail: true, 29 | // We generate sourcemaps in production. This is slow but gives good results. 30 | // You can exclude the *.map files from the build during deployment. 31 | devtool: 'source-map', 32 | entry: { 33 | // In production, we only want to load the polyfills and the app code. 34 | app: [ 35 | // path.join(paths.appSrc, 'polyfills'), 36 | path.join(paths.appSrc, 'main'), 37 | ], 38 | vendor: [ 39 | 'react', 40 | 'react-dom', 41 | 'recompose', 42 | 'react-router', 43 | ], 44 | }, 45 | output: { 46 | // The build folder. 47 | path: process.env.BUILD || paths.appBuild, 48 | // Generated JS file names (with nested folders). 49 | filename: 'static/js/[name].[chunkhash:8].js', 50 | chunkFilename: 'static/js/[name].[chunkhash:8].chunk.js', 51 | // We inferred the "public path" (such as / or /my-project) from homepage. 52 | publicPath, 53 | }, 54 | resolve: { 55 | alias: { 56 | // 'react-components-markdown': path.join(__dirname, '../src'), 57 | }, 58 | modulesDirectories: [ 59 | paths.appSrc, 60 | 'node_modules', 61 | ], 62 | extensions: ['', '.web.js', '.js', '.jsx'], // eslint-disable-line 63 | }, 64 | resolveLoader: { 65 | root: paths.appNodeModules, 66 | }, 67 | postcss: [ 68 | autoprefixer({ browsers: ['last 2 versions'] }), 69 | ], 70 | recordsPath: path.resolve(__dirname, '.webpack-records.json'), 71 | plugins: [ 72 | // Generates an `index.html` file with the