A webpack 4 frontend architecture series: building a scaffold from scratch, integrating React, Redux, webpack 4, gitignore, formatting, env config, HMR, debugging.
webpack scaffold
Environment
First: development environment Use VS Code and github. Concepts are covered in many places already, so I will keep this brief—see the docs. OK, let us start with how to use it. We will build the features a typical project needs one by one. First, a small example to see what the bundling flow looks like—no long talk.
Initialize the project with npm (yarn works too). Run
npm init -yto generatepackage.json(cnpm is a bit faster if you switch to it).Install the HTML Boilerplate plugin in VS Code, then writing HTML is comfortable. Create a file and type
html:5+ Enter to get a simple HTML5 file.Add a simple CSS file and JS file—the classic trio—and you have the simplest possible web page.
1 2 3 4 5 6 7 8 9 10 11 12 13 14<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <link rel="stylesheet" href="./main.css"> <title>Hello Webpack</title> </head> <body> <h2>Say hello to webpack4!</h2> <script src="./bundle.js"></script> </body> </html>
http-server
- To quickly preview the HTML page, install a helper globally:
cnpm install http-server -g - Since we will use webpack, install it too:
cnpm install webpack -g - Start the page with http-server:
http-server -p 3000, then visit http://127.0.0.1:3000/ to see the simple page
Getting started with webpack
The simple static page is done. Next we use webpack to bundle and minify JS.
- Try it once:
./node_modules/webpack/bin/webpack.js ./main.js bundle.jsThen change the scriptsrcin HTML tobundle.js, open the page—it still works. Webpack packedmain.jsintobundle.js. Open the bundle and see what the output looks like. - Of course we should not edit HTML and type commands by hand every time. Webpack gives you a config file, and with
scriptsinpackage.jsonyou can add shortcuts so you are not typing commands all day. - Formal bundling
webpack.config.jslooks like this:1 2 3 4 5 6 7 8 9 10 11const path = require("path"); module.exports = { entry: { app: "./src/main.js" }, output: { publicPath: __dirname + "/build/", // JS public path or CDN base path: path.resolve(__dirname, "build"), // output directory for bundles filename: "bundle.js" } };- Result
Similar to the CLI run above, but shown through a config file—meaning what the comments say. Do not know
entryandoutput? Please skim the docs (Chinese is fine) for a rough idea [see the link at the top]. After writing this, runwebpackin the project root. Put the command inpackage.jsonscriptsso later you runnpm run buildfor the build. Example (webpack installed globally here for convenience): - Put the command in package.json
1 2"build": "webpack" - OK, each build creates a
builddirectory. I do not want to delete it manually every time, so run a clean before build. Installcnpm install rmdir-cli, then the build script becomes:Adjust the layout slightly: add a1"build": "rmdir-cli build && webpack --watch"srcfolder for JS and only change theentrypath inwebpack.config.js. If HTML references the bundle, point the scriptsrcatbuild/. See my GitHub repo for full code.watchrecompiles when files change so you see updates immediately.
- Try it once:
Bundled output for different module styles Webpack supports ES6, CommonJS, and AMD in your JS. Example with ES6:
main.js
1 2 3 4 5import addtwo from "./add"; console.log("javascript say hello."); addtwo(1, 2);add.js
1 2 3 4 5export default (a, b) => { console.log("a+b =", a + b); return a + b; };Rebuild, run, open Chrome DevTools on the HTML page, and check that
a+b = 3is logged. Done!A peek at the bundle:
1 2 3 4 5 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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91!(function(e) { var t = {}; function r(n) { if (t[n]) return t[n].exports; var o = (t[n] = { i: n, l: !1, exports: {} }); return e[n].call(o.exports, o, o.exports, r), (o.l = !0), o.exports; } (r.m = e), (r.c = t), (r.d = function(e, t, n) { r.o(e, t) || Object.defineProperty(e, t, { enumerable: !0, get: n }); }), (r.r = function(e) { "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(e, "__esModule", { value: !0 }); }), (r.t = function(e, t) { if ((1 & t && (e = r(e)), 8 & t)) return e; if (4 & t && "object" == typeof e && e && e.__esModule) return e; var n = Object.create(null); if ( (r.r(n), Object.defineProperty(n, "default", { enumerable: !0, value: e }), 2 & t && "string" != typeof e) ) for (var o in e) r.d( n, o, function(t) { return e[t]; }.bind(null, o) ); return n; }), (r.n = function(e) { var t = e && e.__esModule ? function() { return e.default; } : function() { return e; }; return r.d(t, "a", t), t; }), (r.o = function(e, t) { return Object.prototype.hasOwnProperty.call(e, t); }), (r.p = "/Users/hyy/github/webpack4/build/"), r((r.s = 0)); })([ function(e, t, r) { "use strict"; r.r(t); console.log("javascript say hello."), ((e, t) => (console.log("a+b =", e + t), e + t))(1, 2); } ]);Getting sleepy—stopping here for today. Not sure what else to say, so I will wrap with a bit of filler!