├── .github
└── FUNDING.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── examples
├── basic
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ └── src
│ │ └── index.js
├── with-custom-babel-config
│ ├── .babelrc
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ └── src
│ │ └── index.js
├── with-custom-webpack-config
│ ├── .gitignore
│ ├── README.md
│ ├── backpack.config.js
│ ├── package.json
│ └── services
│ │ └── main.js
├── with-flowtype
│ ├── .babelrc
│ ├── .flowconfig
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ └── src
│ │ └── index.js
├── with-jest
│ ├── .babelrc
│ ├── .gitignore
│ ├── README.md
│ ├── __tests__
│ │ └── createServer.test.js
│ ├── package.json
│ └── src
│ │ ├── createServer.js
│ │ └── index.js
└── with-typescript
│ ├── .gitignore
│ ├── README.md
│ ├── backpack.config.js
│ ├── package.json
│ ├── src
│ └── main.ts
│ └── tsconfig.json
├── lerna.json
├── package.json
├── packages
├── babel-preset-backpack
│ ├── README.md
│ ├── index.js
│ └── package.json
└── backpack-core
│ ├── .gitignore
│ ├── README.md
│ ├── babel.js
│ ├── bin
│ ├── backpack
│ ├── build
│ └── dev
│ ├── config
│ ├── paths.js
│ └── webpack.config.js
│ └── package.json
└── yarn.lock
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [jaredpalmer]
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/osx,git,node,linux,macos,windows,intellij,visualstudiocode
3 |
4 | ### Git ###
5 | *.orig
6 |
7 | ### Intellij ###
8 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
9 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
10 |
11 | # User-specific stuff:
12 | .idea/**/workspace.xml
13 | .idea/**/tasks.xml
14 | .idea/dictionaries
15 |
16 | # Sensitive or high-churn files:
17 | .idea/**/dataSources/
18 | .idea/**/dataSources.ids
19 | .idea/**/dataSources.xml
20 | .idea/**/dataSources.local.xml
21 | .idea/**/sqlDataSources.xml
22 | .idea/**/dynamic.xml
23 | .idea/**/uiDesigner.xml
24 |
25 | # Gradle:
26 | .idea/**/gradle.xml
27 | .idea/**/libraries
28 |
29 | # CMake
30 | cmake-build-debug/
31 |
32 | # Mongo Explorer plugin:
33 | .idea/**/mongoSettings.xml
34 |
35 | ## File-based project format:
36 | *.iws
37 |
38 | ## Plugin-specific files:
39 |
40 | # IntelliJ
41 | /out/
42 |
43 | # mpeltonen/sbt-idea plugin
44 | .idea_modules/
45 |
46 | # JIRA plugin
47 | atlassian-ide-plugin.xml
48 |
49 | # Cursive Clojure plugin
50 | .idea/replstate.xml
51 |
52 | # Ruby plugin and RubyMine
53 | /.rakeTasks
54 |
55 | # Crashlytics plugin (for Android Studio and IntelliJ)
56 | com_crashlytics_export_strings.xml
57 | crashlytics.properties
58 | crashlytics-build.properties
59 | fabric.properties
60 |
61 | ### Intellij Patch ###
62 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
63 |
64 | # *.iml
65 | # modules.xml
66 | # .idea/misc.xml
67 | # *.ipr
68 |
69 | # Sonarlint plugin
70 | .idea/sonarlint
71 |
72 | ### Linux ###
73 | *~
74 |
75 | # temporary files which can be created if a process still has a handle open of a deleted file
76 | .fuse_hidden*
77 |
78 | # KDE directory preferences
79 | .directory
80 |
81 | # Linux trash folder which might appear on any partition or disk
82 | .Trash-*
83 |
84 | # .nfs files are created when an open file is removed but is still being accessed
85 | .nfs*
86 |
87 | ### macOS ###
88 | *.DS_Store
89 | .AppleDouble
90 | .LSOverride
91 |
92 | # Icon must end with two \r
93 | Icon
94 |
95 | # Thumbnails
96 | ._*
97 |
98 | # Files that might appear in the root of a volume
99 | .DocumentRevisions-V100
100 | .fseventsd
101 | .Spotlight-V100
102 | .TemporaryItems
103 | .Trashes
104 | .VolumeIcon.icns
105 | .com.apple.timemachine.donotpresent
106 |
107 | # Directories potentially created on remote AFP share
108 | .AppleDB
109 | .AppleDesktop
110 | Network Trash Folder
111 | Temporary Items
112 | .apdisk
113 |
114 | ### Node ###
115 | # Logs
116 | logs
117 | *.log
118 | npm-debug.log*
119 | yarn-debug.log*
120 | yarn-error.log*
121 |
122 | # Runtime data
123 | pids
124 | *.pid
125 | *.seed
126 | *.pid.lock
127 |
128 | # Directory for instrumented libs generated by jscoverage/JSCover
129 | lib-cov
130 |
131 | # Coverage directory used by tools like istanbul
132 | coverage
133 |
134 | # nyc test coverage
135 | .nyc_output
136 |
137 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
138 | .grunt
139 |
140 | # Bower dependency directory (https://bower.io/)
141 | bower_components
142 |
143 | # node-waf configuration
144 | .lock-wscript
145 |
146 | # Compiled binary addons (http://nodejs.org/api/addons.html)
147 | build/Release
148 |
149 | # Dependency directories
150 | node_modules/
151 | jspm_packages/
152 |
153 | # Typescript v1 declaration files
154 | typings/
155 |
156 | # Optional npm cache directory
157 | .npm
158 |
159 | # Optional eslint cache
160 | .eslintcache
161 |
162 | # Optional REPL history
163 | .node_repl_history
164 |
165 | # Output of 'npm pack'
166 | *.tgz
167 |
168 | # Yarn Integrity file
169 | .yarn-integrity
170 |
171 | # dotenv environment variables file
172 | .env
173 |
174 |
175 | ### OSX ###
176 |
177 | # Icon must end with two \r
178 |
179 | # Thumbnails
180 |
181 | # Files that might appear in the root of a volume
182 |
183 | # Directories potentially created on remote AFP share
184 |
185 | ### VisualStudioCode ###
186 | .vscode/*
187 | !.vscode/settings.json
188 | !.vscode/tasks.json
189 | !.vscode/launch.json
190 | !.vscode/extensions.json
191 | .history
192 |
193 | ### Windows ###
194 | # Windows thumbnail cache files
195 | Thumbs.db
196 | ehthumbs.db
197 | ehthumbs_vista.db
198 |
199 | # Folder config file
200 | Desktop.ini
201 |
202 | # Recycle Bin used on file shares
203 | $RECYCLE.BIN/
204 |
205 | # Windows Installer files
206 | *.cab
207 | *.msi
208 | *.msm
209 | *.msp
210 |
211 | # Windows shortcuts
212 | *.lnk
213 |
214 |
215 | # End of https://www.gitignore.io/api/osx,git,node,linux,macos,windows,intellij,visualstudiocode
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 |
4 |
5 |
6 |
7 | **Table of Contents**
8 |
9 | * [Contributor Covenant Code of Conduct](#contributor-covenant-code-of-conduct)
10 | * [Our Pledge](#our-pledge)
11 | * [Our Standards](#our-standards)
12 | * [Our Responsibilities](#our-responsibilities)
13 | * [Scope](#scope)
14 | * [Enforcement](#enforcement)
15 | * [Attribution](#attribution)
16 |
17 |
18 |
19 | ## Our Pledge
20 |
21 | In the interest of fostering an open and welcoming environment, we as
22 | contributors and maintainers pledge to making participation in our project and
23 | our community a harassment-free experience for everyone, regardless of age, body
24 | size, disability, ethnicity, gender identity and expression, level of experience,
25 | nationality, personal appearance, race, religion, or sexual identity and
26 | orientation.
27 |
28 | ## Our Standards
29 |
30 | Examples of behavior that contributes to creating a positive environment
31 | include:
32 |
33 | * Using welcoming and inclusive language
34 | * Being respectful of differing viewpoints and experiences
35 | * Gracefully accepting constructive criticism
36 | * Focusing on what is best for the community
37 | * Showing empathy towards other community members
38 |
39 | Examples of unacceptable behavior by participants include:
40 |
41 | * The use of sexualized language or imagery and unwelcome sexual attention or
42 | advances
43 | * Trolling, insulting/derogatory comments, and personal or political attacks
44 | * Public or private harassment
45 | * Publishing others' private information, such as a physical or electronic
46 | address, without explicit permission
47 | * Other conduct which could reasonably be considered inappropriate in a
48 | professional setting
49 |
50 | ## Our Responsibilities
51 |
52 | Project maintainers are responsible for clarifying the standards of acceptable
53 | behavior and are expected to take appropriate and fair corrective action in
54 | response to any instances of unacceptable behavior.
55 |
56 | Project maintainers have the right and responsibility to remove, edit, or
57 | reject comments, commits, code, wiki edits, issues, and other contributions
58 | that are not aligned to this Code of Conduct, or to ban temporarily or
59 | permanently any contributor for other behaviors that they deem inappropriate,
60 | threatening, offensive, or harmful.
61 |
62 | ## Scope
63 |
64 | This Code of Conduct applies both within project spaces and in public spaces
65 | when an individual is representing the project or its community. Examples of
66 | representing a project or community include using an official project e-mail
67 | address, posting via an official social media account, or acting as an appointed
68 | representative at an online or offline event. Representation of a project may be
69 | further defined and clarified by project maintainers.
70 |
71 | ## Enforcement
72 |
73 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
74 | reported by contacting the project team at [info@palmer.net](mailto:info@palmer.net). All
75 | complaints will be reviewed and investigated and will result in a response that
76 | is deemed necessary and appropriate to the circumstances. The project team is
77 | obligated to maintain confidentiality with regard to the reporter of an incident.
78 | Further details of specific enforcement policies may be posted separately.
79 |
80 | Project maintainers who do not follow or enforce the Code of Conduct in good
81 | faith may face temporary or permanent repercussions as determined by other
82 | members of the project's leadership.
83 |
84 | ## Attribution
85 |
86 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
87 | available at [http://contributor-covenant.org/version/1/4][version]
88 |
89 | [homepage]: http://contributor-covenant.org
90 | [version]: http://contributor-covenant.org/version/1/4/
91 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to Contribute to Backpack
2 |
3 |
4 |
5 |
6 |
7 | **Table of Contents**
8 |
9 | * [How to Contribute to Backpack](#how-to-contribute-to-backpack)
10 | * [Getting started](#getting-started)
11 | * [Using Lerna](#using-lerna)
12 | * [Support](#support)
13 |
14 |
15 |
16 | ## Getting started
17 |
18 | First fork the project to your GitHub account. Then clone it, checkout a new branch, and install the dependencies.
19 |
20 | ```bash
21 | git clone https://github.com/YOUR_USERNAME/backpack.git
22 | cd backpack
23 | git checkout -B YOUR_BRANCH_NAME
24 | npm install
25 | ```
26 |
27 | Backpack is a monorepo powered by [Lerna](https://lernajs.io/). After you install, Lerna will run its `bootstrap` command that will install all dependencies in each of the `packages` and `examples` folders, build each example, and symlink all interdependencies.
28 |
29 | Now you can run all of the examples with your **local** version of Backpack. When you make edits to anything in `packages`, you (will probably) need to restart the example you are working with to pick up changes. Imagine the following workflow:
30 |
31 | In one terminal tab, I open and run the `basic` example:
32 |
33 | ```
34 | cd examples/basic
35 | npm run dev
36 | ```
37 |
38 | Next, I open up `packages/backpack-core/webpack.config.js` in my editor and make some changes to the webpack configuration focusing on development mode.
39 |
40 | To try out these local changes, I would need to:
41 |
42 | * Kill the running example (i.e. `CMD + c`)
43 | * Rerun it to pickup changes (i.e. `npm run dev`)
44 |
45 | That's it.
46 |
47 | ## Using Lerna
48 |
49 | When moving between branches, it's a good idea to work with a fresh install.
50 |
51 | In your project's root run the following:
52 |
53 | ```bash
54 | ./node_modules/bin/lerna clean
55 | ./node_modules/bin/lerna bootstrap
56 | ```
57 |
58 | This will clean out, reinstall, rebuild, and symlink all of the `examples` and `packages` properly.
59 |
60 | ## Support
61 |
62 | * Join the #backpack channel in our public Slack group. Sign up at [https://palmer.chat](https://palmer.chat/)
63 | * File an issue on GitHub
64 | * Tweet to or DM [@jaredpalmer](https://twitter.com/jaredpalmer)
65 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 The Palmer Group https://palmer.net
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 |
3 | 
4 | [](https://badge.fury.io/js/backpack-core) [](https://discord.com/invite/RevdZTYMzr)
5 |
6 | Backpack is minimalistic build system for Node.js. Inspired by Facebook's [create-react-app](https://github.com/facebookincubator/create-react-app), Zeit's [Next.js](https://github.com/zeit/next.js), and Remy's [Nodemon](https://github.com/remy/nodemon), Backpack lets you create modern Node.js apps and services with zero configuration. Backpack handles all the file-watching, live-reloading, transpiling, and bundling, so you don't have to. It comes with a few ~~conventions~~ defaults (like support for the latest JavaScript awesomeness (i.e. async/await, object rest spread, and class properties)), but everything can be customized to fit your project's needs. Best of all, you can easily add Backpack to your existing Node.js project with just a single dependency.
7 |
8 | **Backpack comes with the "battery-pack included":**
9 |
10 | * Latest ES6 features (including module syntax, async/await, object rest spread)
11 | * SUPER friendly, human readable error messages
12 | * Live reload (on saves, add/delete file, etc.)
13 | * Zero-config, one dependency.
14 |
15 | HOWEVER, you can configure Backpack to your project's needs by extending [the underlying Webpack 4 configuration](#custom-configuration).
16 |
17 | **PLEASE READ:** If you're thinking of using Backpack with React.js, you should use [Razzle](https://github.com/jaredpalmer/razzle) instead. It is a project purpose-built for SSR React with an almost identical API.
18 |
19 |
20 |
21 |
22 |
23 | **Table of Contents**
24 |
25 | * [How to use](#how-to-use)
26 | * [Custom configuration](#custom-configuration)
27 | * [Customizing webpack config](#customizing-webpack-config)
28 | * [Customizing babel config](#customizing-babel-config)
29 | * [Building for Production](#building-for-production)
30 | * [CLI Commands](#cli-commands)
31 | * [`backpack dev`](#backpack-dev)
32 | * [`backpack build`](#backpack-build)
33 | * [FAQ](#faq)
34 | * [Inspiration](#inspiration)
35 | * [Authors](#authors)
36 |
37 |
38 |
39 | ## How to use
40 |
41 | Install it:
42 |
43 | ```bash
44 | npm i backpack-core --save
45 | ```
46 |
47 | and add a script to your package.json like this:
48 |
49 | ```json
50 | {
51 | "scripts": {
52 | "dev": "backpack"
53 | }
54 | }
55 | ```
56 |
57 | After that there are just a few ~~conventions~~ defaults:
58 |
59 | * `src/index.js`: the entry of your app.
60 |
61 | ...actually that's it.
62 |
63 | You can then run your application in development mode:
64 |
65 | ```bash
66 | npm run dev
67 | ```
68 |
69 | Successful builds will show a console like this. _Note: screenshot taken from running the [basic example](https://github.com/palmerhq/backpack/tree/master/examples/basic)_
70 |
71 |
72 | ### Custom configuration
73 |
74 | For custom advanced behavior, you can create a `backpack.config.js` in the root of your project's directory (next to `package.json`).
75 |
76 | ```js
77 | // backpack.config.js
78 | // IMPORTANT: This file is not going through babel transformation.
79 | // You can however use the ES2015 features supported by your Node.js version.
80 | module.exports = {
81 | /* config options here */
82 | };
83 | ```
84 |
85 | ### Customizing webpack config
86 |
87 | [Example](https://github.com/palmerhq/backpack/tree/master/examples/with-custom-webpack-config)
88 |
89 | To extend webpack, you can define a function that extends its config via `backpack.config.js`.
90 |
91 | ```js
92 | // backpack.config.js
93 | module.exports = {
94 | webpack: (config, options, webpack) => {
95 | // Perform customizations to config
96 | // Important: return the modified config
97 | return config;
98 | },
99 | };
100 | ```
101 |
102 | ### Customizing babel config
103 |
104 | [Example](https://github.com/palmerhq/backpack/tree/master/examples/with-custom-babel-config)
105 |
106 | To extend our usage of `babel`, you can define a `.babelrc` file at the root of your app. This file is optional.
107 |
108 | If found, Backpack will consider it to be the _source of truth_. Thus it must define what Backpack needs as well, which is the `backpack-core/babel` preset.
109 |
110 | This is designed so that you are not surprised by modifications we could make to the default `babel` configurations.
111 |
112 | Here's an example `.babelrc` file:
113 |
114 | ```js
115 | {
116 | "presets": [
117 | "backpack-core/babel",
118 | "stage-0"
119 | ]
120 | }
121 | ```
122 |
123 | _Note: This works [exactly like Next.js does](https://github.com/zeit/next.js#customizing-babel-config)._
124 |
125 | ### Building for Production
126 |
127 | Add a npm script for the build step:
128 |
129 | ```json
130 | {
131 | "scripts": {
132 | "dev": "backpack",
133 | "build": "backpack build"
134 | }
135 | }
136 | ```
137 |
138 | Then run the build command and start your app
139 |
140 | ```bash
141 | npm run build
142 | node ./build/main.js
143 | ```
144 |
145 | ## CLI Commands
146 |
147 | ### `backpack dev`
148 |
149 | Runs backpack in development mode.
150 |
151 | Your code will reload if you make edits.
152 | You will see the build errors in the console that look like this.
153 |
154 |
155 |
156 | ### `backpack build`
157 |
158 | Builds the app for production to the `build` folder.
159 | It correctly bundles your production mode and optimizes the build for the best performance.
160 |
161 | You can run your production application with the following command:
162 |
163 | ```bash
164 | node ./build/main.js
165 | ```
166 |
167 | Your application is ready to be deployed!
168 |
169 | _Note: Make sure to add the `build` directory to your `.gitignore` to keep compiled code out of your git repository_
170 |
171 | ## FAQ
172 |
173 |
174 | Is this like Create-React-App or Next.js?
175 |
176 | Yes and No.
177 |
178 | Yes in that they will all make your life easier.
179 |
180 | No in that it that Backpack is focused on server-only applications. You should use create-react-app or Next.js for your frontend and then build your backend with Backpack.
181 |
182 |
183 |
184 |
185 | Can I use this with React to build a universal app?
186 |
187 | Technically, yes. However, we strongly advise against it at the moment. Backpack handles file-watching and reloading in a way that will make things like webpack-hot-middleware annoying to work with.
188 |
189 |
190 |
191 | What syntactic features are transpiled? How do I change them?
192 |
193 | We track V8. Since V8 has wide support for ES6, we don't transpile it. Since V8 doesn’t support async/await and class properties yet, we transpile those.
194 |
195 | See [this](https://github.com/palmerhq/backpack/blob/master/packages/backpack-core/config/webpack.config.js#L83) and [this](https://github.com/palmerhq/backpack#customizing-webpack)
196 |
197 |
198 |
199 | Why is it called Backpack?
200 |
201 | Backpack is focused on server-only applications. We've been using it for building out Node.js backends and microservices. Under the hood, Webpack and a few other tools make the magic happen. Hence Backend + Webpack = *Backpack*.
202 |
203 |
204 | ## Inspiration
205 |
206 | * [jlongster/backend-with-webpack](https://github.com/jlongster/backend-with-webpack)
207 | * [nyt/kyt](https://github.com/NYTimes/kyt)
208 | * [zeit/next.js](https://github.com/zeit/next.js)
209 | * [facebookincubator/create-react-app](https://github.com/facebookincubator/create-react-app)
210 |
211 | ## Authors
212 |
213 | * Jared Palmer ([@jaredpalmer](https://twitter.com/jaredpalmer)) - The Palmer Group
214 |
--------------------------------------------------------------------------------
/examples/basic/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
3 | npm-debug.log
4 |
--------------------------------------------------------------------------------
/examples/basic/README.md:
--------------------------------------------------------------------------------
1 | # Basic Example
2 |
3 | ## How to use
4 |
5 | Download the example [or clone the whole project](https://github.com/palmerhq/backpack.git):
6 |
7 | ```bash
8 | curl https://codeload.github.com/palmerhq/backpack/tar.gz/master | tar -xz --strip=2 backpack-master/examples/basic
9 | cd basic
10 | ```
11 |
12 | Install it and run:
13 |
14 | ```bash
15 | npm install
16 | npm run dev
17 | ```
18 |
19 | ## Idea behind the example
20 |
21 | This is a basic example of how to use Backpack in a project. It is a simple Express.js server. It demonstrates how easy it is to use
22 | Backpack in a project. It also shows off some of the default syntax features provided by Backpack such as async/await and object rest spread
23 | as well as a Webpack environment flag (`__DEV__`).
24 |
--------------------------------------------------------------------------------
/examples/basic/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "backpack-examples-basic",
3 | "version": "0.8.4",
4 | "scripts": {
5 | "start": "node ./build/main.js",
6 | "dev": "backpack dev",
7 | "build": "backpack build",
8 | "postinstall": "backpack build"
9 | },
10 | "license": "MIT",
11 | "dependencies": {
12 | "backpack-core": "^0.8.4",
13 | "express": "^4.16.2"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/examples/basic/src/index.js:
--------------------------------------------------------------------------------
1 | import express from 'express';
2 |
3 | const app = express();
4 |
5 | app.get('/', async (req, res) => {
6 | const thing = await Promise.resolve({ one: 'two' }) // async/await!
7 | .catch(e => res.json({ error: e.message }));
8 | return res.json({ ...thing, hello: 'world' }); // object-rest-spread!
9 | });
10 |
11 | const port = process.env.PORT || 3000;
12 |
13 | app.listen(port, err => {
14 | if (err) {
15 | console.error(err);
16 | }
17 |
18 | if (__DEV__) {
19 | // webpack flags!
20 | console.log('> in development');
21 | }
22 |
23 | console.log(`> listening on port ${port}`);
24 | });
25 |
--------------------------------------------------------------------------------
/examples/with-custom-babel-config/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "backpack-core/babel"
4 |
5 | ],
6 | "plugins": [
7 | "@babel/plugin-proposal-do-expressions"
8 | ]
9 | }
--------------------------------------------------------------------------------
/examples/with-custom-babel-config/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
3 | npm-debug.log
4 |
--------------------------------------------------------------------------------
/examples/with-custom-babel-config/README.md:
--------------------------------------------------------------------------------
1 | # Custom Babel Configuration Example
2 |
3 | ## How to use
4 |
5 | Download the example [or clone the whole project](https://github.com/palmerhq/backpack.git):
6 |
7 | ```bash
8 | curl https://codeload.github.com/palmerhq/backpack/tar.gz/master | tar -xz --strip=2 backpack-master/examples/with-custom-babel-config
9 | cd with-custom-babel-config
10 | ```
11 |
12 | Install it and run:
13 |
14 | ```bash
15 | npm install
16 | npm run dev
17 | ```
18 |
19 | ## Idea behind the example
20 |
21 | This demonstrates how extend the default Backpack babel configuration with a custom `.babelrc` file.
22 | More specifically, this example shows how to add all `stage-0` transformations through `babel-preset-stage-0`.
23 |
24 | Be sure to include `backpack-core/babel` in your `.babelrc` as the first item in the presets array:
25 |
26 | ```json
27 | {
28 | "presets": ["backpack-core/babel", "..."]
29 | }
30 | ```
31 |
--------------------------------------------------------------------------------
/examples/with-custom-babel-config/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "backpack-examples-with-custom-babel-config",
3 | "version": "0.8.4",
4 | "scripts": {
5 | "start": "node ./build/main.js",
6 | "dev": "backpack dev",
7 | "build": "backpack build",
8 | "postinstall": "backpack build"
9 | },
10 | "license": "MIT",
11 | "dependencies": {
12 | "@babel/core": "^7.0.0",
13 | "@babel/plugin-proposal-do-expressions": "^7.0.0",
14 | "backpack-core": "^0.8.4",
15 | "express": "^4.14.0"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/with-custom-babel-config/src/index.js:
--------------------------------------------------------------------------------
1 | const randomNo = Math.ceil(Math.random() * 100)
2 |
3 | // `do` expressions are a new syntax proposal.
4 | // @see: https://babeljs.io/docs/plugins/transform-do-expressions/
5 | const message = do {
6 | if (randomNo < 30) {
7 | 'Do not give up. Try again.'
8 | } else if (randomNo < 60) {
9 | 'You are a lucky guy'
10 | } else {
11 | 'You are soooo lucky!'
12 | }
13 | }
14 |
15 | console.log(`number: ${randomNo}`)
16 | console.log(`message: ${message}`)
17 |
--------------------------------------------------------------------------------
/examples/with-custom-webpack-config/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
3 | npm-debug.log
4 |
--------------------------------------------------------------------------------
/examples/with-custom-webpack-config/README.md:
--------------------------------------------------------------------------------
1 | # Custom Webpack Configuration Example
2 |
3 | ## How to use
4 |
5 | Download the example [or clone the whole project](https://github.com/palmerhq/backpack.git):
6 |
7 | ```bash
8 | curl https://codeload.github.com/palmerhq/backpack/tar.gz/master | tar -xz --strip=2 backpack-master/examples/with-custom-webpack-config
9 | cd with-custom-webpack-config
10 | ```
11 |
12 | Install it and run:
13 |
14 | ```bash
15 | npm install
16 | npm run dev
17 | ```
18 |
19 | ## Idea behind the example
20 |
21 | This demonstrates how to customize the underlying Webpack 2 configuration in a Backpack project using a `backpack.config.js` file.
22 | The app itself is exactly the same simple Express.js server in the basic example. However, the entry point to the application has been
23 | changed from `./src/index.js` to `./services/main.js`.
24 |
--------------------------------------------------------------------------------
/examples/with-custom-webpack-config/backpack.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | webpack: (config, options, webpack) => {
3 | // Perform customizations to config
4 | // Important: return the modified config
5 |
6 | // changes the name of the entry point from index -> main.js
7 | config.entry.main = [
8 | './services/main.js'
9 | ]
10 |
11 | return config
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/examples/with-custom-webpack-config/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "backpack-examples-with-custom-webpack-config",
3 | "version": "0.8.4",
4 | "scripts": {
5 | "start": "node ./build/main.js",
6 | "dev": "backpack dev",
7 | "build": "backpack build",
8 | "postinstall": "backpack build"
9 | },
10 | "license": "MIT",
11 | "dependencies": {
12 | "backpack-core": "^0.8.4",
13 | "express": "^4.14.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/examples/with-custom-webpack-config/services/main.js:
--------------------------------------------------------------------------------
1 | import express from 'express';
2 |
3 | const app = express();
4 |
5 | app.get('/', async (req, res) => {
6 | const thing = await Promise.resolve({ one: 'two' }) // async/await!
7 | .catch(e => res.json({ error: e.message }));
8 | return res.json({ ...thing, hello: 'world' }); // object-rest-spread!
9 | });
10 |
11 | const port = process.env.PORT || 3000;
12 |
13 | app.listen(port, err => {
14 | if (err) {
15 | console.error(err);
16 | }
17 |
18 | if (__DEV__) {
19 | // webpack flags!
20 | console.log('> in development');
21 | }
22 |
23 | console.log(`> listening on port ${port}`);
24 | });
25 |
--------------------------------------------------------------------------------
/examples/with-flowtype/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "backpack-core/babel"
4 | ],
5 | "plugins": [
6 | "@babel/plugin-transform-flow-strip-types"
7 | ]
8 | }
--------------------------------------------------------------------------------
/examples/with-flowtype/.flowconfig:
--------------------------------------------------------------------------------
1 | [ignore]
2 | .*/node_modules/invariant/.*
3 |
4 | [include]
5 |
6 | [libs]
7 |
8 | [options]
9 |
--------------------------------------------------------------------------------
/examples/with-flowtype/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
3 | npm-debug.log
4 |
--------------------------------------------------------------------------------
/examples/with-flowtype/README.md:
--------------------------------------------------------------------------------
1 | # FlowType Example
2 |
3 | ## How to use
4 |
5 | Download the example [or clone the whole project](https://github.com/palmerhq/backpack.git):
6 |
7 | ```bash
8 | curl https://codeload.github.com/palmerhq/backpack/tar.gz/master | tar -xz --strip=2 backpack-master/examples/with-flowtype
9 | cd with-flowtype
10 | ```
11 |
12 | Install it and run:
13 |
14 | ```bash
15 | npm install
16 | npm run dev
17 | ```
18 |
19 | ## Idea behind the example
20 |
21 | This demonstrates how to add [Flow](https://flowtype.org/) to your Backpack project. Flow is a static type checker that helps you write code
22 | with fewer bugs. Check out this [introduction to using static types in JavaScript](https://medium.com/@preethikasireddy/why-use-static-types-in-javascript-part-1-8382da1e0adb) if you are new to this concept.
23 |
24 | To learn more about Flow, take a look at [its documentation](https://flowtype.org/).
25 |
--------------------------------------------------------------------------------
/examples/with-flowtype/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "backpack-examples-with-flowtype",
3 | "version": "0.8.4",
4 | "scripts": {
5 | "start": "node ./build/main.js",
6 | "flow": "flow",
7 | "dev": "backpack dev",
8 | "build": "backpack build",
9 | "postinstall": "backpack build"
10 | },
11 | "license": "MIT",
12 | "dependencies": {
13 | "@babel/core": "^7.1.2",
14 | "@babel/plugin-transform-flow-strip-types": "7.4.4",
15 | "backpack-core": "^0.8.4",
16 | "express": "^4.14.0",
17 | "flow-bin": "^0.101.1"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/with-flowtype/src/index.js:
--------------------------------------------------------------------------------
1 | /* @flow */
2 |
3 | // This will throw an error when you run `npm run flow`.
4 | // change the return type to `:number`, to remove the error.
5 | function foo(x: string, y: number): string {
6 | return x.length * y;
7 | }
8 |
9 | console.log(foo("Hello", 42));
10 |
--------------------------------------------------------------------------------
/examples/with-jest/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "backpack-core/babel"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/examples/with-jest/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
3 | npm-debug.log
4 |
--------------------------------------------------------------------------------
/examples/with-jest/README.md:
--------------------------------------------------------------------------------
1 | # Example with Jest
2 |
3 | ## How to use
4 |
5 | Download the example [or clone the whole project](https://github.com/palmerhq/backpack.git):
6 |
7 | ```bash
8 | curl https://codeload.github.com/palmerhq/backpack/tar.gz/master | tar -xz --strip=2 backpack-master/examples/with-jest
9 | cd with-jest
10 | ```
11 |
12 | Install it and run the tests:
13 |
14 | ```bash
15 | npm install
16 | npm t
17 | ```
18 |
19 | ## Idea behind the example
20 |
21 | This is an example of how to use the Jest test framework with Backpack.
22 |
23 | **Points of Interest:**
24 |
25 | * New `.babelrc` file with `presets: ["backpack-core/babel"]`
26 | * Add `babel-jest` and `jest-cli` to devDependencies in `package.json`
27 | * Add `"jest"` section to `package.json` to manage Jest configuration
28 | * Demonstrate how to write HTTP test with `supertest-as-promised`
29 |
--------------------------------------------------------------------------------
/examples/with-jest/__tests__/createServer.test.js:
--------------------------------------------------------------------------------
1 | /* global it, expect, describe */
2 |
3 | import createServer from '../src/createServer';
4 | import request from 'supertest';
5 |
6 | const app = createServer();
7 |
8 | describe('Backpack with Jest', () => {
9 | it('Object Rest Spread', () => {
10 | const hello = { hello: 'world' };
11 | const other = { ...hello, nice: 'to meet you' };
12 |
13 | expect(other).toEqual({ hello: 'world', nice: 'to meet you' });
14 | });
15 |
16 | it('HTTP Request', async () => {
17 | const res = await request(app).get('/');
18 | expect(res.status).toBe(200);
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/examples/with-jest/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "backpack-examples-with-jest",
3 | "version": "0.8.4",
4 | "scripts": {
5 | "start": "node ./build/main.js",
6 | "test": "NODE_ENV=test jest",
7 | "dev": "backpack dev",
8 | "build": "backpack build",
9 | "postinstall": "backpack build"
10 | },
11 | "license": "MIT",
12 | "dependencies": {
13 | "@babel/core": "^7.1.2",
14 | "backpack-core": "^0.8.4",
15 | "express": "^4.14.0"
16 | },
17 | "devDependencies": {
18 | "babel-jest": "^24.8.0",
19 | "jest-cli": "^24.8.0",
20 | "supertest": "^4.0.2"
21 | },
22 | "jest": {
23 | "testEnvironment": "node",
24 | "transformIgnorePatterns": [
25 | "[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$"
26 | ],
27 | "globals": {
28 | "__DEV__": true
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/examples/with-jest/src/createServer.js:
--------------------------------------------------------------------------------
1 | import express from 'express';
2 | export default () => {
3 | const app = express();
4 |
5 | app.get('/', async (req, res) => {
6 | const thing = await Promise.resolve({ one: 'two' }) // async/await!
7 | .catch(e => res.json({ error: e.message }));
8 | return res.json({ ...thing, hello: 'world' }); // object-rest-spread!
9 | });
10 |
11 | return app;
12 | };
13 |
--------------------------------------------------------------------------------
/examples/with-jest/src/index.js:
--------------------------------------------------------------------------------
1 | import createServer from './createServer'
2 |
3 | const port = process.env.PORT || 3000
4 | const app = createServer()
5 |
6 | app.listen(port, (err) => {
7 | if (err) {
8 | console.error(err)
9 | }
10 |
11 | if (__DEV__) { // webpack flags!
12 | console.log('> in development')
13 | }
14 | console.log(`> listening on port ${port}`)
15 | })
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/examples/with-typescript/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
3 | npm-debug.log
4 |
--------------------------------------------------------------------------------
/examples/with-typescript/README.md:
--------------------------------------------------------------------------------
1 | # Custom Webpack Configuration With Typescript Example
2 |
3 | ## How to use
4 |
5 | Download the example (or clone the whole project)[https://github.com/palmerhq/backpack.git]:
6 |
7 | ```bash
8 | curl https://codeload.github.com/palmerhq/backpack/tar.gz/master | tar -xz --strip=2 backpack-master/examples/with-typescript
9 | cd with-typescript
10 | ```
11 |
12 | Install it and run:
13 |
14 | ```bash
15 | npm install
16 | npm run dev
17 | ```
18 |
19 | ## Idea behind the example
20 |
21 | This demonstrates how to customize the underlying Webpack 2 configuration in a Backpack project using a `backpack.config.js` file.
22 | The app itself is exactly the same project as the Webpack configuration example. However, the express application is written in TypeScript.
23 |
--------------------------------------------------------------------------------
/examples/with-typescript/backpack.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | webpack: (config, options, webpack) => {
3 | config.entry.main = [
4 | './src/main.ts'
5 | ]
6 |
7 | config.resolve = {
8 | extensions: [".ts", ".js", ".json"]
9 | };
10 |
11 | config.module.rules.push(
12 | {
13 | test: /\.ts$/,
14 | loader: 'awesome-typescript-loader'
15 | }
16 | );
17 |
18 | return config
19 | }
20 | }
--------------------------------------------------------------------------------
/examples/with-typescript/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "backpack-examples-with-typescript",
3 | "version": "0.8.4",
4 | "scripts": {
5 | "start": "node ./build/main.js",
6 | "dev": "backpack dev",
7 | "build": "backpack build"
8 | },
9 | "license": "MIT",
10 | "dependencies": {
11 | "@types/express": "^4.0.34",
12 | "awesome-typescript-loader": "^5.2.1",
13 | "backpack-core": "^0.8.4",
14 | "express": "^4.14.0",
15 | "typescript": "^3.5.2"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/with-typescript/src/main.ts:
--------------------------------------------------------------------------------
1 | import * as express from "express"
2 |
3 | declare var __DEV__: boolean;
4 |
5 | export class Server {
6 | public app: express.Express;
7 | public port: number;
8 |
9 | constructor() {
10 | this.app = express();
11 | this.port = this.getPort();
12 | this.setRoutes();
13 | this.start();
14 | }
15 |
16 | private start = (): void => {
17 | this.app.listen(this.port, this.onListen);
18 | }
19 |
20 | private onListen = (err: any): void => {
21 | if (err) {
22 | console.error(err)
23 | return;
24 | }
25 |
26 | if (__DEV__) {
27 | console.log('> in development')
28 | }
29 |
30 | console.log(`> listening on port ${this.port}`)
31 | };
32 |
33 | private getPort = (): number => parseInt(process.env.PORT, 10) || 3000;
34 |
35 | private setRoutes = (): void => {
36 | this.app.get('/', this.getHomepage);
37 | }
38 |
39 | private async getHomepage(req: express.Request, res: express.Response): Promise {
40 | try {
41 | const thing = await Promise.resolve({ one: 'two' })
42 | return res.json({ ...thing, hello: 'world' })
43 | } catch (e) {
44 | return res.json({ error: e.message })
45 | }
46 | };
47 | }
48 |
49 | module.exports = new Server().app;
--------------------------------------------------------------------------------
/examples/with-typescript/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": [
4 | "es5",
5 | "es2015.promise"
6 | ]
7 | }
8 | }
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.8.4",
3 | "npmClient": "yarn",
4 | "useWorkspaces": true,
5 | "packages": [
6 | "packages/*",
7 | "examples/basic*"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "devDependencies": {
4 | "lerna": "^3.15.0"
5 | },
6 | "scripts": {
7 | "bootstrap-workaround": "lerna exec yarn && lerna link && lerna run prepublish && lerna run prepare",
8 | "postinstall": "yarn bootstrap-workaround",
9 | "bootstrap": "lerna bootstrap",
10 | "clean": "lerna clean",
11 | "purge-lock-files": "rm -rf ./yarn.lock && rm -rf ./**/**/yarn.lock",
12 | "purge-modules": "lerna clean --yes && rm -rf ./node_modules & rm -rf ./tools",
13 | "purge": "yarn purge-modules && yarn purge-lock-files",
14 | "reinstall": "yarn purge && yarn",
15 | "build": "lerna run build --stream --parallel"
16 | },
17 | "workspaces": [
18 | "packages/*",
19 | "examples/*"
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/packages/babel-preset-backpack/README.md:
--------------------------------------------------------------------------------
1 | # babel-preset-backpack
2 |
3 | This package includes the [Babel](https://babeljs.io) preset used by [Backpack](https://github/com/palmerhq/backpack)
4 |
5 | ## Usage in Backpack Projects
6 |
7 | The easiest way to use this configuration is with Backpack, which includes it by default. **You don’t need to install it separately in Backpack projects.**
8 |
9 | ## Usage Outside of Backpack
10 |
11 | If you want to use this Babel preset in a project not built with Backpack, you can install it with following steps.
12 |
13 | First, [install Babel](https://babeljs.io/docs/setup/).
14 |
15 | Then create a file named `.babelrc` with following contents in the root folder of your project:
16 |
17 | ```js
18 | {
19 | "presets": ["backpack"]
20 | }
21 | ```
22 |
23 | This preset uses the `useBuiltIns` option with [transform-object-rest-spread](http://babeljs.io/docs/plugins/transform-object-rest-spread/), which assumes that `Object.assign` is available or polyfilled.
24 |
25 | ---
26 |
27 | MIT License
28 |
--------------------------------------------------------------------------------
/packages/babel-preset-backpack/index.js:
--------------------------------------------------------------------------------
1 | module.exports = function() {
2 | const path = require('path');
3 |
4 | const preset = {
5 | presets: [
6 | [
7 | require.resolve('@babel/preset-env'),
8 | {
9 | targets: {
10 | node: 'current',
11 | },
12 | // Webpack takes care of modules, so we don't have to.
13 | modules: false,
14 | },
15 | ],
16 | ],
17 | plugins: [
18 | // class { handleThing = () => { } }
19 | require.resolve('@babel/plugin-proposal-class-properties'),
20 |
21 | // The following two plugins use Object.assign directly, instead of Babel's
22 | // extends helper. Note that this assumes `Object.assign` is available.
23 | // { ...todo, completed: true }
24 | [
25 | require.resolve('@babel/plugin-proposal-object-rest-spread'),
26 | {
27 | useBuiltIns: true,
28 | },
29 | ],
30 |
31 | [
32 | require.resolve('@babel/plugin-transform-regenerator'),
33 | {
34 | // Async functions are converted to generators by babel-preset-env (which
35 | // is based on babel-preset-latest)
36 | async: false,
37 | },
38 | ],
39 |
40 | // This is so we don't need to add `babel-polyfill` to our webpack `entry`.
41 | // Unlike `babel-polyfill`, `babel-runtime` + the transform do not pollute
42 | // the global namespace. Yay.
43 | // @see https://medium.com/@jcse/clearing-up-the-babel-6-ecosystem-c7678a314bf3#.7j10g8yn0
44 | [
45 | require.resolve('@babel/plugin-transform-runtime'),
46 | {
47 | helpers: false,
48 | regenerator: true,
49 | // Resolve the Babel runtime relative to the config.
50 | absoluteRuntime: path.dirname(
51 | require.resolve('@babel/runtime/package')
52 | ),
53 | },
54 | ],
55 | ],
56 | };
57 |
58 | const v = process.versions.node.split('.');
59 | if ((v[0] >= 7 && v[1] >= 6) || v[0] >= 8) {
60 | preset.presets[0].exclude = [
61 | '@babel/plugin-transform-regenerator',
62 | '@babel/transform-async-to-generator',
63 | ];
64 | }
65 | if (process.env.NODE_ENV === 'test' || process.env.BABEL_ENV === 'test') {
66 | preset.plugins.push.apply(preset.plugins, [
67 | // We always include this plugin regardless of environment
68 | // because of a Babel bug that breaks object rest/spread without it:
69 | // https://github.com/babel/babel/issues/4851
70 | require.resolve('@babel/plugin-transform-parameters'),
71 | // Jest needs this to work properly with import/export syntax
72 | [
73 | require.resolve('@babel/plugin-transform-modules-commonjs'),
74 | { loose: true },
75 | ],
76 | ]);
77 | }
78 |
79 | return preset;
80 | };
81 |
--------------------------------------------------------------------------------
/packages/babel-preset-backpack/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "babel-preset-backpack",
3 | "version": "0.8.4",
4 | "description": "Babel preset for Backpack projects",
5 | "repository": "palmerhq/backpack",
6 | "author": "jaredpalmer",
7 | "license": "MIT",
8 | "homepage": "https://github.com/palmerhq/backpack#readme",
9 | "bugs": {
10 | "url": "https://github.com/palmerhq/backpack/issues"
11 | },
12 | "files": [
13 | "index.js"
14 | ],
15 | "dependencies": {
16 | "@babel/core": "^7.4.5",
17 | "@babel/plugin-proposal-class-properties": "^7.4.4",
18 | "@babel/plugin-proposal-object-rest-spread": "^7.4.4",
19 | "@babel/plugin-transform-modules-commonjs": "^7.4.4",
20 | "@babel/plugin-transform-parameters": "^7.4.4",
21 | "@babel/plugin-transform-regenerator": "^7.4.5",
22 | "@babel/plugin-transform-runtime": "^7.4.4",
23 | "@babel/preset-env": "^7.4.5",
24 | "@babel/runtime": "^7.4.5",
25 | "babel-loader": "^8.0.6"
26 | },
27 | "keywords": [
28 | "babel",
29 | "es6",
30 | "node",
31 | "backpack"
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/packages/backpack-core/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 |
--------------------------------------------------------------------------------
/packages/backpack-core/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | 
4 | [](https://badge.fury.io/js/backpack-core) [](https://gitter.im/palmerhq/backpack?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
5 |
6 | Backpack is minimalistic build system for Node.js. Inspired by Facebook's [create-react-app](https://github.com/facebookincubator/create-react-app), Zeit's [Next.js](https://github.com/zeit/next.js), and Remy's [Nodemon](https://github.com/remy/nodemon), Backpack lets you create modern Node.js apps and services with zero configuration. Backpack handles all the file-watching, live-reloading, transpiling, and bundling, so you don't have to. It comes with a few ~~conventions~~ defaults (like support for the latest JavaScript awesomeness (i.e. async/await, object rest spread, and class properties)), but everything can be customized to fit your project's needs. Best of all, you can easily add Backpack to your existing Node.js project with just a single dependency.
7 |
8 | **Backpack comes with the "battery-pack included":**
9 |
10 | * Latest ES6 features (including module syntax, async/await, object rest spread)
11 | * SUPER friendly, human readable error messages
12 | * Live reload (on saves, add/delete file, etc.)
13 | * Zero-config, one dependency.
14 |
15 | HOWEVER, you can configure Backpack to your project's needs by extending [the underlying Webpack 2 configuration](#custom-configuration).
16 |
17 | ## How to use
18 |
19 | Install it:
20 |
21 | ```bash
22 | npm i backpack-core --save
23 | ```
24 |
25 | and add a script to your package.json like this:
26 |
27 | ```json
28 | {
29 | "scripts": {
30 | "dev": "backpack"
31 | }
32 | }
33 | ```
34 |
35 | After that there are just a few ~~conventions~~ defaults:
36 |
37 | * `src/index.js`: the entry of your app.
38 |
39 | ...actually that's it.
40 |
41 | You can then run your application in development mode:
42 |
43 | ```bash
44 | npm run dev
45 | ```
46 |
47 | Successful builds will show a console like this. _Note: screenshot taken from running the [basic example](https://github.com/palmerhq/backpack/tree/master/examples/basic)_
48 |
49 |
50 | ### Custom configuration
51 |
52 | For custom advanced behavior, you can create a `backpack.config.js` in the root of your project's directory (next to `package.json`).
53 |
54 | ```js
55 | // backpack.config.js
56 | // IMPORTANT: This file is not going through babel transformation.
57 | // You can however use the ES2015 features supported by your Node.js version.
58 | module.exports = {
59 | /* config options here */
60 | };
61 | ```
62 |
63 | ### Customizing webpack config
64 |
65 | [Example](https://github.com/palmerhq/backpack/tree/master/examples/with-custom-webpack-config)
66 |
67 | To extend webpack, you can define a function that extends its config via `backpack.config.js`.
68 |
69 | ```js
70 | // backpack.config.js
71 | module.exports = {
72 | webpack: (config, options, webpack) => {
73 | // Perform customizations to config
74 | // Important: return the modified config
75 | return config;
76 | },
77 | };
78 | ```
79 |
80 | ### Customizing babel config
81 |
82 | [Example](https://github.com/palmerhq/backpack/tree/master/examples/with-custom-babel-config)
83 |
84 | To extend our usage of `babel`, you can define a `.babelrc` file at the root of your app. This file is optional.
85 |
86 | If found, Backpack will consider it to be the _source of truth_. Thus it must define what Backpack needs as well, which is the `backpack-core/babel` preset.
87 |
88 | This is designed so that you are not surprised by modifications we could make to the default `babel` configurations.
89 |
90 | Here's an example `.babelrc` file:
91 |
92 | ```js
93 | {
94 | "presets": [
95 | "backpack-core",
96 | "stage-0"
97 | ],
98 | }
99 | ```
100 |
101 | _Note: This works [exactly like Next.js does](https://github.com/zeit/next.js#customizing-babel-config)._
102 |
103 | ### Building for Production
104 |
105 | Add a npm script for the build step:
106 |
107 | ```json
108 | {
109 | "scripts": {
110 | "dev": "backpack",
111 | "build": "backpack build"
112 | }
113 | }
114 | ```
115 |
116 | Then run the build command and start your app
117 |
118 | ```bash
119 | npm run build
120 | node ./build/main.js
121 | ```
122 |
123 | ## CLI Commands
124 |
125 | ### `backpack dev`
126 |
127 | Runs backpack in development mode.
128 |
129 | Your code will reload if you make edits.
130 | You will see the build errors in the console that look like this.
131 |
132 |
133 |
134 | ### `backpack build`
135 |
136 | Builds the app for production to the `build` folder.
137 | It correctly bundles your production mode and optimizes the build for the best performance.
138 |
139 | You can run your production application with the following command:
140 |
141 | ```bash
142 | node ./build/main.js
143 | ```
144 |
145 | Your application is ready to be deployed!
146 |
147 | _Note: Make sure to add the `build` directory to your `.gitignore` to keep compiled code out of your git repository_
148 |
149 | ## FAQ
150 |
151 |
152 | Is this like Create-React-App or Next.js?
153 |
154 | Yes and No.
155 |
156 | Yes in that they will all make your life easier.
157 |
158 | No in that it that Backpack is focused on server-only applications. You should use create-react-app or Next.js for your frontend and then build your backend with Backpack.
159 |
160 |
161 |
162 |
163 | Can I use this with React to build a universal app?
164 |
165 | Technically, yes. However, we strongly advise against it at the moment. Backpack handles file-watching and reloading in a way that will make things like webpack-hot-middleware annoying to work with.
166 |
167 |
168 |
169 | What syntactic features are transpiled? How do I change them?
170 |
171 | We track V8. Since V8 has wide support for ES6 and async and await, we transpile those. Since V8 doesn’t support class decorators, we don’t transpile those.
172 |
173 | See [this](https://github.com/palmerhq/backpack/blob/master/packages/backpack-core/config/webpack.config.js#L83) and [this](https://github.com/palmerhq/backpack#customizing-webpack)
174 |
175 |
176 |
177 | Why is it called Backpack?
178 |
179 | Backpack is focused on server-only applications. We've been using it for building out Node.js backends and microservices. Under the hood, Webpack and a few other tools make the magic happen. Hence Backend + Webpack = *Backpack*.
180 |
181 |
182 | ## Inspiration
183 |
184 | * [jlongster/backend-with-webpack](https://github.com/jlongster/backend-with-webpack)
185 | * [nyt/kyt](https://github.com/NYTimes/kyt)
186 | * [zeit/next.js](https://github.com/zeit/next.js)
187 | * [facebookincubator/create-react-app](https://github.com/facebookincubator/create-react-app)
188 |
189 | ## Authors
190 |
191 | * Jared Palmer ([@jaredpalmer](https://twitter.com/jaredpalmer)) - The Palmer Group
192 |
193 | ---
194 |
195 | MIT License
196 |
--------------------------------------------------------------------------------
/packages/backpack-core/babel.js:
--------------------------------------------------------------------------------
1 | module.exports = require('babel-preset-backpack');
2 |
--------------------------------------------------------------------------------
/packages/backpack-core/bin/backpack:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | const path = require('path')
3 | const spawn = require('cross-spawn')
4 | const pkg = require('../package.json')
5 |
6 | const defaultCommand = 'dev'
7 | const commands = new Set([
8 | 'init',
9 | 'build',
10 | 'start',
11 | defaultCommand
12 | ])
13 |
14 | let cmd = process.argv[2]
15 | let args
16 |
17 | if (new Set(['--version', '-v']).has(cmd)) {
18 | console.log('backpack v' + pkg.version)
19 | process.exit(0)
20 | }
21 |
22 | if (new Set(['--help', '-h']).has(cmd)) {
23 | console.log(`
24 | Usage
25 | $ backpack
26 | Available commands
27 | ${Array.from(commands).join(', ')}
28 | For more information run a command with the --help flag
29 | $ backpack --help
30 | `)
31 | process.exit(0)
32 | }
33 |
34 | if (commands.has(cmd)) {
35 | args = process.argv.slice(3)
36 | } else {
37 | cmd = defaultCommand
38 | args = process.argv.slice(2)
39 | }
40 |
41 | const bin = path.resolve(path.join(__dirname, cmd))
42 |
43 | const startProcess = () => {
44 | const proc = spawn(bin, args, { stdio: 'inherit'})
45 | proc.on('close', (code) => process.exit(code))
46 | proc.on('error', (err) => {
47 | console.error(err)
48 | process.exit(1)
49 | })
50 | return proc
51 | }
52 |
53 | const proc = startProcess()
54 |
--------------------------------------------------------------------------------
/packages/backpack-core/bin/build:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env node
2 | const webpack = require('webpack')
3 | const defaultConfig = require('../config/webpack.config')
4 | const path = require('path')
5 | const fs = require('fs')
6 |
7 | process.on('SIGINT', process.exit)
8 |
9 | const options = {
10 | env: process.env.NODE_ENV || 'production'
11 | }
12 |
13 | const configPath = path.resolve('backpack.config.js')
14 | let userConfig = {}
15 |
16 | if (fs.existsSync(configPath)) {
17 | const userConfigModule = require(configPath)
18 | userConfig = userConfigModule.default || userConfigModule
19 | }
20 |
21 | const serverConfig = userConfig.webpack
22 | ? userConfig.webpack(defaultConfig(options), options, webpack)
23 | : defaultConfig(options)
24 |
25 | process.on('SIGINT', process.exit)
26 |
27 | const serverCompiler = webpack(serverConfig)
28 |
29 | serverCompiler.run((error, stats) => {
30 | if (error || stats.hasErrors()) {
31 | process.exitCode = 1;
32 | }
33 | })
34 |
--------------------------------------------------------------------------------
/packages/backpack-core/bin/dev:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env node
2 | const webpack = require('webpack')
3 | const nodemon = require('nodemon')
4 | const paths = require('../config/paths')
5 | const once = require('ramda').once
6 | const defaultConfig = require('../config/webpack.config')
7 | const path = require('path')
8 | const fs = require('fs')
9 |
10 | const options = {
11 | env: 'development'
12 | }
13 |
14 | const configPath = path.resolve('backpack.config.js')
15 | let userConfig = {}
16 |
17 | if (fs.existsSync(configPath)) {
18 | const userConfigModule = require(configPath)
19 | userConfig = userConfigModule.default || userConfigModule
20 | }
21 |
22 | const serverConfig = userConfig.webpack
23 | ? userConfig.webpack(defaultConfig(options), options, webpack)
24 | : defaultConfig(options)
25 |
26 | process.on('SIGINT', process.exit)
27 |
28 | const serverCompiler = webpack(serverConfig)
29 |
30 | const startServer = () => {
31 | const serverPaths = Object
32 | .keys(serverCompiler.options.entry)
33 | .map(entry => path.join(serverCompiler.options.output.path, `${entry}.js`))
34 | nodemon({ script: serverPaths[0], watch: serverPaths, nodeArgs: process.argv.slice(2) })
35 | .on('quit', process.exit)
36 | }
37 |
38 | const startServerOnce = once((err, stats) => {
39 | if (err) return
40 | startServer()
41 | })
42 | serverCompiler.watch(serverConfig.watchOptions || {}, startServerOnce)
43 |
--------------------------------------------------------------------------------
/packages/backpack-core/config/paths.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const rootPath = path.resolve(process.cwd())
3 | const buildPath = path.join(rootPath, 'build')
4 | const publicBuildPath = path.join(buildPath, 'public')
5 |
6 | module.exports = {
7 | rootPath,
8 | buildPath,
9 | publicBuildPath,
10 | publicSrcPath: path.join(rootPath, 'public'),
11 | serverSrcPath: path.join(rootPath, 'src'),
12 | serverBuildPath: buildPath,
13 | userNodeModulesPath: path.join(rootPath, 'node_modules'),
14 | publicPath: '/',
15 | serverUrl: 'http://localhost:3000'
16 | }
17 |
--------------------------------------------------------------------------------
/packages/backpack-core/config/webpack.config.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const webpack = require('webpack');
3 | const nodeExternals = require('webpack-node-externals');
4 | const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
5 | const config = require('./paths');
6 | const path = require('path');
7 | const babelPreset = require('../babel');
8 |
9 | // This is the Webpack configuration.
10 | // It is focused on developer experience and fast rebuilds.
11 | module.exports = options => {
12 | const babelRcPath = path.resolve('.babelrc');
13 | const hasBabelRc = fs.existsSync(babelRcPath);
14 | const mainBabelOptions = {
15 | babelrc: true,
16 | cacheDirectory: true,
17 | presets: [],
18 | };
19 |
20 | if (hasBabelRc) {
21 | console.log('> Using .babelrc defined in your app root');
22 | } else {
23 | mainBabelOptions.presets.push(require.resolve('../babel'));
24 | }
25 |
26 | return {
27 | // Webpack v4 add a mode configuration option tells webpack to use its
28 | // built-in optimizations accordingly.
29 | // @see https://webpack.js.org/concepts/mode/
30 | mode: options.env === 'development' ? 'development' : 'production',
31 | // Webpack can target multiple environments such as `node`,
32 | // `browser`, and even `electron`. Since Backpack is focused on Node,
33 | // we set the default target accordingly.
34 | target: 'node',
35 | // The benefit of Webpack over just using babel-cli or babel-node
36 | // command is sourcemap support. Although it slows down compilation,
37 | // it makes debugging dramatically easier.
38 | devtool: 'source-map',
39 | // Webpack allows you to define externals - modules that should not be
40 | // bundled. When bundling with Webpack for the backend - you usually
41 | // don't want to bundle its node_modules dependencies. This creates an externals
42 | // function that ignores node_modules when bundling in Webpack.
43 | // @see https://github.com/liady/webpack-node-externals
44 | externals: [
45 | nodeExternals({
46 | modulesFromFile: true,
47 | whitelist: [
48 | /\.(eot|woff|woff2|ttf|otf)$/,
49 | /\.(svg|png|jpg|jpeg|gif|ico|webm)$/,
50 | /\.(mp4|mp3|ogg|swf|webp)$/,
51 | /\.(css|scss|sass|less|styl)$/,
52 | ],
53 | })
54 | ],
55 | // As of Webpack 2 beta, Webpack provides performance hints.
56 | // Since we are not targeting a browser, bundle size is not relevant.
57 | // Additionally, the performance hints clutter up our nice error messages.
58 | performance: {
59 | hints: false,
60 | },
61 | // Since we are wrapping our own webpack config, we need to properly resolve
62 | // Backpack's and the given user's node_modules without conflict.
63 | resolve: {
64 | extensions: ['.js', '.json'],
65 | // modules: [config.userNodeModulesPath, path.resolve(__dirname, '../node_modules')]
66 | },
67 | resolveLoader: {
68 | // modules: [config.userNodeModulesPath, path.resolve(__dirname, '../node_modules')]
69 | },
70 | node: {
71 | __filename: true,
72 | __dirname: true,
73 | },
74 | entry: {
75 | main: [`${config.serverSrcPath}/index.js`],
76 | },
77 | // This sets the default output file path, name, and compile target
78 | // module type. Since we are focused on Node.js, the libraryTarget
79 | // is set to CommonJS2
80 | output: {
81 | path: config.serverBuildPath,
82 | filename: '[name].js',
83 | sourceMapFilename: '[name].map',
84 | publicPath: config.publicPath,
85 | libraryTarget: 'commonjs2',
86 | },
87 | // Define a few default Webpack loaders. Notice the use of the new
88 | // Webpack 2 configuration: module.rules instead of module.loaders
89 | module: {
90 | rules: [
91 | // Process JS with Babel (transpiles ES6 code into ES5 code).
92 | {
93 | test: /\.(js|jsx)$/,
94 | loader: require.resolve('babel-loader'),
95 | exclude: [/node_modules/, config.buildPath],
96 | options: mainBabelOptions,
97 | },
98 | ],
99 | },
100 | // A few commonly used plugins have been removed from Webpack v4.
101 | // Now instead, these plugins are avaliable as "optimizations".
102 | // @see https://webpack.js.org/configuration/optimization/
103 | optimization: {
104 | // optimization.noEmitOnErrors prevents Webpack
105 | // The NoEmitOnErrorsPlugin plugin prevents Webpack
106 | // from printing out compile time stats to the console.
107 | noEmitOnErrors: true,
108 | },
109 | plugins: [
110 | // We define some sensible Webpack flags. One for the Node environment,
111 | // and one for dev / production. These become global variables. Note if
112 | // you use something like eslint or standard in your editor, you will
113 | // want to configure __DEV__ as a global variable accordingly.
114 | new webpack.DefinePlugin({
115 | 'process.env.NODE_ENV': JSON.stringify(options.env),
116 | __DEV__: options.env === 'development',
117 | }),
118 | // In order to provide sourcemaps, we automagically insert this at the
119 | // top of each file using the BannerPlugin.
120 | new webpack.BannerPlugin({
121 | raw: true,
122 | entryOnly: false,
123 | banner: `require('${
124 | // Is source-map-support installed as project dependency, or linked?
125 | require.resolve('source-map-support').indexOf(process.cwd()) === 0
126 | ? // If it's resolvable from the project root, it's a project dependency.
127 | 'source-map-support/register'
128 | : // It's not under the project, it's linked via lerna.
129 | require.resolve('source-map-support/register')
130 | }');`,
131 | }),
132 | // The FriendlyErrorsWebpackPlugin (when combined with source-maps)
133 | // gives Backpack its human-readable error messages.
134 | new FriendlyErrorsWebpackPlugin({
135 | clearConsole: options.env === 'development',
136 | }),
137 | ],
138 | };
139 | };
140 |
--------------------------------------------------------------------------------
/packages/backpack-core/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "backpack-core",
3 | "version": "0.8.4",
4 | "description": "Backpack is a minimalistic build system for Node.js",
5 | "repository": "palmerhq/backpack",
6 | "author": "@jaredpalmer",
7 | "license": "MIT",
8 | "bugs": {
9 | "url": "https://github.com/palmerhq/backpack/issues"
10 | },
11 | "bin": {
12 | "backpack": "./bin/backpack"
13 | },
14 | "dependencies": {
15 | "@babel/core": "^7.4.5",
16 | "babel-loader": "^8.0.6",
17 | "babel-preset-backpack": "^0.8.4",
18 | "cross-spawn": "^6.0.5",
19 | "friendly-errors-webpack-plugin": "^1.7.0",
20 | "json-loader": "^0.5.7",
21 | "nodemon": "^1.19.1",
22 | "ramda": "^0.26.1",
23 | "source-map-support": "^0.5.12",
24 | "webpack": "^4.35.0",
25 | "webpack-node-externals": "^1.7.2"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------