UNPKG

12.9 kBMarkdownView Raw
1<div align="right">
2 <h1 align="right">
3 <img height=75 src="./docs/assets/readme-header.png" alt="webpack base">
4 </h1>
5
6 <!-- prettier-ignore-start -->
7 <a href="https://www.npmjs.com/package/@crystal-ball/webpack-base">
8 <img src="https://img.shields.io/npm/v/@crystal-ball/webpack-base" alt="Package version" valign="text-top"/>
9 </a>
10 <a href="https://www.npmjs.com/package/@crystal-ball/webpack-base">
11 <img src="https://img.shields.io/npm/dt/@crystal-ball/webpack-base?color=blue" alt="NPM downloads" valign="text-top" />
12 </a>
13 <a href="https://github.com/crystal-ball/webpack-base/actions?workflow=CI%2FCD">
14 <img src="https://github.com/crystal-ball/webpack-base/workflows/CI%2FCD/badge.svg" alt="Build status" valign="text-top" />
15 </a>
16 <a href="https://snyk.io/test/github/crystal-ball/webpack-base?targetFile=package.json">
17 <img src="https://snyk.io/test/github/crystal-ball/webpack-base/badge.svg?targetFile=package.json" alt="Known vulnerabilities" valign="text-top" />
18 </a>
19 <a href="https://codeclimate.com/github/crystal-ball/webpack-base/test_coverage">
20 <img src="https://api.codeclimate.com/v1/badges/eee860e3bd1519dacf5e/test_coverage" alt="Test coverage" valign="text-top" />
21 </a>
22 <a href="https://codeclimate.com/github/crystal-ball/webpack-base/maintainability">
23 <img src="https://api.codeclimate.com/v1/badges/eee860e3bd1519dacf5e/maintainability" alt="Maintainability" valign="text-top" />
24 </a>
25 <code>:status&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code>
26
27 <br />
28 <a href="https://renovatebot.com/">
29 <img src="https://img.shields.io/badge/Renovate-enabled-32c3c2.svg" alt="Renovate" valign="text-top" />
30 </a>
31 <a href="https://commitizen.github.io/cz-cli/">
32 <img src="https://img.shields.io/badge/Commitizen-%E2%9C%93%20friendly-10e67b" alt="Commitizen friendly" valign="text-top" />
33 </a>
34 <a href="https://github.com/crystal-ball/webpack-base#workspaces/-projects-5b88b5c9af3c0a2186966767/board?repos=136812233">
35 <img src="https://img.shields.io/badge/ZenHub-managed-5e60ba.svg" alt="ZenHub" valign="text-top" />
36 </a>
37 <a href="https://semantic-release.gitbook.io/semantic-release/">
38 <img src="https://img.shields.io/badge/%F0%9F%93%A6%F0%9F%9A%80-semantic_release-e10079.svg" alt="Semantic Release" valign="text-top"/>
39 </a>
40 <a href="./CODE_OF_CONDUCT.md">
41 <img src="https://img.shields.io/badge/Contributor%20Covenant-v2.0-de8cf2.svg" alt="Contributor Covenant" valign="text-top" />
42 </a>
43 <code>:integrations</code>
44
45 <br />
46 <a href="https://github.com/crystal-ball">
47 <img src="https://img.shields.io/badge/%F0%9F%94%AE%E2%9C%A8-contains_magic-D831D7.svg" alt="Contains magic" valign="text-top" />
48 </a>
49 <a href="https://github.com/crystal-ball/crystal-ball.github.io">
50 <img src="https://img.shields.io/badge/%F0%9F%92%96%F0%9F%8C%88-full_of_love-F5499E.svg" alt="Full of love" valign="text-top" />
51 </a>
52 <code>:flair&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code>
53 <!-- prettier-ignore-end -->
54
55 <h1></h1>
56 <br />
57 <p align="center">
58 <em>This package generates a base webpack configuration and dependencies for
59 React web and Electron applications. Users can customize the generated base
60 configurations to meet the specific needs of any project.</em>
61 </p>
62 <br />
63</div>
64
65- [Setup](#-setup) - Installation and file setup instructions
66- [Project defaults](#=project-defaults) - Documentation on default project
67 structure used
68- [Configuration API](#-configuration-api) - Documentation on customizing
69 generated configurations
70- [Featureset](#-featureset) - Overview of the supported magic
71- [Electron support](#-electron-support) - Using within an Electron project
72- [Docker support](#-docker-support) - Using within a Docker workflow
73- [Accessing resources](#-accessing-resources) - Accessing loaders and plugins
74 directly
75- [Developing](#-developing) - How to develop the project
76- [Testing](#-testing) - How to test the project
77- [Roadmap](#-roadmap) - TODO items and contributing suggestions
78- [Contributing](#-contributing) - Yes please! 😍
79
80---
81
82## ⚙️ Setup
83
84**1. Install**
85
86```bash
87npm i -D @crystal-ball/webpack-base
88```
89
90**2. Add `package.json` commands**
91
92```json
93{
94 "scripts": {
95 "build": "NODE_ENV=production webpack --mode=production",
96 "start": "NODE_ENV=development webpack-dev-server --mode=development"
97 }
98}
99```
100
101**3. Add configuration files**
102
103Add configuration files for webpack and Babel to the project root. The
104[@crystal-ball/react-application-prototype][] is a complete working reference
105application using this package. Projects require a:
106
107- `.browserslistrc`
108- `.eslintrc.js`
109- `babel.config.js`
110- `webpack.config.js`
111
112## 📦 Project defaults
113
114Out of the box all of the webpack-base loaders and plugins will work with
115projects that use the default project directory structure:
116
117```
118project
119├─ / src
120│ └─ / api
121│ └─ / components
122│ └─ / dux
123│ └─ / media
124│ │ └─ / icons
125│ └─ / styles
126│ └─ / utils
127│ ├─ index.html
128│ ├─ index.js
129│ └─ index.scss
130├─ / static
131│ └─ favicon.ico
132├─ .browserslistrc
133├─ .eslintrc.js
134├─ babel.config.js
135└─ webpack.config.js
136```
137
138### Directories
139
140- **src** - Project source code root directory.
141- **src/media/icons** - The SVG symbol sprite loader will sprite any SVG icons
142 imported from this directory.
143- **src/styles** - SCSS files in this directory can be imported with the `@`
144 alias from anywhere in the project.
145- **src/api**, **src/components**, **src/dux** and **src/utils** - Suggested but
146 not required directory structure for organizing application code by domain
147- **static** - The static folder can be used as an escape hatch for including
148 assets that are not directly imported in the project code. The contents are
149 copied to the output directory during builds.
150
151## 📝 Configuration API
152
153The project `webpack.config.js` should call the webpack-base package to generate
154a base configuration. The base configuration can then be modified in any way to
155support specific project needs.
156
157```javascript
158// webpack.config.js
159const webpackBase = require('@crystal-ball/webpack-base')
160
161module.exports = () => {
162 const { configs } = webpackBase(/* options */)
163
164 /*
165 * Handle non-standard, advanced project customization by directly updating
166 * the generated base configs.
167 */
168 configs.rules.push({
169 /* some custom loader */
170 })
171
172 return configs
173}
174```
175
176### Options
177
178The base configurations generated by the package can be customized by passing an
179options object:
180
181```javascript
182const { configs } = webpackBase{
183 devServer,
184 envVars
185 paths,
186 sassOptions,
187 target,
188})
189```
190
191### Available path configs
192
193```javascript
194const paths = {
195 /**
196 * Project root directory that is used by webpack (eg to handle resolutions).
197 * webpack base attempts to automatically set the project context, but it
198 * can help fix resolution errors to specify it.
199 * @default /
200 */
201 context,
202 /**
203 * SVG files imported from these directories will be loaded+sprited using the
204 * `SVGSymbolSprite` package.
205 * @default ['/src/media/icons']
206 */
207 iconSpriteIncludes,
208 /**
209 * JS files imported from these directories will be loaded using the JS loader.
210 * @default ['/src']
211 */
212 jsLoaderIncludes,
213 /**
214 * Build assets are emitted to this directory.
215 * @default /public
216 */
217 output,
218 /**
219 * Application source files directory. This directory is used as a base for
220 * the icon includes path.
221 * @default /src
222 */
223 src,
224 /**
225 * Application public static files directory. This directory is copied to the
226 * build without manipulation by the `CopyWebpackPlugin` and provides an
227 * escape hatch to include assets in a build without importing them in the
228 * application source.
229 * @default /static
230 */
231 static,
232}
233```
234
235## 😍 Featureset
236
237- JS loader setup to transpile all source in the `jsLoaderIncludes` with the
238 `babel-loader`
239- Sourcemaps for dev and prod environments
240- Handles adding scripts to `index.html`
241- Friendly errors
242- Dev server with hot reloading
243- Progress indicators
244- Production optimizations including uglify and module concatenation
245- Output directory cleaning
246- Injected `PUBLIC_PATH` for routing
247- `DEVTOOL` environment variable will override source maps
248- Import paths case is verified to ensure Linux and MacOS compatability
249- Production CSS+JS assets are minified
250- Application logo is used to generate and inject favicon resources in build
251
252### Caching
253
254Long term asset caching is supported by including content based hashes in the
255generated asset filenames.
256
257- `[contenthash]` substitution is included in filenames in production builds to
258 append a hash that will change when the file contents change
259- A single runtime asset is extracted to deduplicate webpack runtime boilerplate
260- Module ids are hashed based on content to prevent import order changes causing
261 all chunks to update.
262- Dynamic imports for code splitting should use webpack magic comments to set a
263 semantic asset name.
264
265### Environment variable injection
266
267The following environment variables are injected by the build:
268
269| Constant | Usage |
270| ------------- | ----------------------------------------------------------------------------- |
271| `NODE_ENV` | Defaults to match NODE_ENV, used by Babili to strip code in prod builds |
272| `DEBUG` | Defaults to false, can be used for adding detailed logging in dev environment |
273| `PUBLIC_PATH` | Defaults to '/', useful for importing media and configuring CDN paths |
274
275Additional environment variables can be passed in an `envVars` option and they
276will be injected into the build
277
278```js
279webpackBase({
280 envVars: { TRACKING_ID: 'x-123456' },
281})
282```
283
284## ⚛️ Electron support
285
286Electron renderer processes can be bundled by passing a `target` flag in
287options:
288
289```javascript
290// webpack.config.js
291const webpackBase = require('@crystal-ball/webpack-base')
292
293module.exports = () => {
294 return webpackBase({ target: 'electron-renderer' }).configs
295}
296```
297
298By default `webpack-base` will look for project source files in `/src/renderer`
299instead of `/src` and builds are output to `/src/build` instead of `/dist`. This
300is for working with Electron build systems.
301
302## 🐳 Docker support
303
304When working within a Docker setup, the dev server port (default `3000`) must be
305exposed and the host set to `0.0.0.0`. Including a start command for Docker is
306recommended:
307
308```json
309{
310 "start:docker": "NODE_ENV=development webpack-dev-server --host=0.0.0.0 --mode=development"
311}
312```
313
314## 🎛 Accessing resources
315
316The configured loaders and plugins can be accessed directly in the return value,
317this is useful when setting up Storybook to pass additional loaders and plugins.
318
319```javascript
320// webpack.config.js
321const webpackBase = require('@crystal-ball/webpack-base')
322
323module.exports = () => {
324 const { loaders, plugins } = webpackBase(/* options */)
325}
326```
327
328#### Returned loaders
329
330```js
331config.loaders = {
332 jsLoader,
333 sassLoader,
334 svgSpriteLoader,
335 svgComponentLoader,
336 fileLoader,
337 rawLoader,
338}
339```
340
341#### Returned plugins
342
343```js
344config.plugins = {
345 progressBarPlugin,
346 environmentPlugin,
347 htmlPlugin,
348 svgSymbolSpritePlugin,
349 copyPlugin,
350 hotModuleReplacementPlugin,
351 friendlyErrorsPlugin,
352}
353```
354
355This can be useful for adding loaders to projects like Storybook.
356
357## 👷‍♀️ Developing
358
359Development and testing of the repository use a Docker workflow to ensure that
360the generated configs work with the packages required and the minimum version of
361Node supported:
362
363```sh
364# Build the image and start the container
365npm run container
366
367# Start the webpack-dev-server 🎉
368npm run start:docker
369```
370
371## ✅ Testing
372
373Unit tests are run with Jest and use snapshots to validate the generated configs
374for development and production environments.
375
376## 🗺 Roadmap
377
378_Interested in contributing? Start here 😍_
379
380- [ ] Investigate usage of [profile][] in builds
381- [ ] Investigate including [Bundle Buddy][bundle] plugin
382
383## 👍 Contributing
384
385All contributions are greatly appreciated 👍🎉. To contribute please:
386
387- Review the repo [Code of Conduct](./CODE_OF_CONDUCT.md), it is not just for
388 show!
389- Review the [Contributing Guide](./CONTRIBUTING.md) for a helpful code overview
390 and repository pull request process details.
391
392### Node version support
393
394Node version running inside Atom's Electron instance is support target to ensure
395users of ESLint import plugin are able to parse these webpack configs.
396
397<!-- Links -->
398<!-- prettier-ignore-start -->
399[bundle]: https://github.com/samccone/bundle-buddy
400[@crystal-ball/react-application-prototype]: https://github.com/crystal-ball/react-application-prototype
401[profile]: https://webpack.js.org/configuration/other-options/#profile
402<!-- prettier-ignore-end -->