From 2154114f92a1357c0d75ec2633049c10cfbea6ba Mon Sep 17 00:00:00 2001 From: Rob Larsen Date: Wed, 22 Mar 2023 15:00:56 -0400 Subject: [PATCH] Webpack build for dist (#2812) Co-authored-by: Christian Oliff --- dist/package.json | 9 ++++-- dist/webpack.common.js | 12 +++++++ dist/webpack.config.dev.js | 16 ++++++++++ dist/webpack.config.js | 16 ---------- dist/webpack.config.prod.js | 28 +++++++++++++++++ docs/usage.md | 63 ++++++++++++++++++++++++++++++++++++- gulpfile.mjs | 1 + package-lock.json | 2 +- src/package.json | 9 ++++-- src/webpack.common.js | 12 +++++++ src/webpack.config.dev.js | 16 ++++++++++ src/webpack.config.js | 16 ---------- src/webpack.config.prod.js | 28 +++++++++++++++++ test/file_existence.mjs | 5 ++- 14 files changed, 192 insertions(+), 41 deletions(-) create mode 100644 dist/webpack.common.js create mode 100644 dist/webpack.config.dev.js delete mode 100644 dist/webpack.config.js create mode 100644 dist/webpack.config.prod.js create mode 100644 src/webpack.common.js create mode 100644 src/webpack.config.dev.js delete mode 100644 src/webpack.config.js create mode 100644 src/webpack.config.prod.js diff --git a/dist/package.json b/dist/package.json index b3cfb9b8..3357b47a 100644 --- a/dist/package.json +++ b/dist/package.json @@ -10,12 +10,15 @@ "author": "", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "start": "webpack-dev-server --open --port 8080" + "start": "webpack serve --open --config webpack.config.dev.js", + "build": "webpack --config webpack.config.prod.js" }, "devDependencies": { - "webpack": "^5.74.0", + "copy-webpack-plugin": "^11.0.0", "html-webpack-plugin": "^5.5.0", + "webpack": "^5.74.0", "webpack-cli": "^4.10.0", - "webpack-dev-server": "^4.11.1" + "webpack-dev-server": "^4.11.1", + "webpack-merge": "^5.8.0" } } diff --git a/dist/webpack.common.js b/dist/webpack.common.js new file mode 100644 index 00000000..18d80c6d --- /dev/null +++ b/dist/webpack.common.js @@ -0,0 +1,12 @@ +const path = require('path'); + +module.exports = { + entry: { + app: './js/app.js', + }, + output: { + path: path.resolve(__dirname, 'dist'), + clean: true, + filename: './js/app.js', + }, +}; \ No newline at end of file diff --git a/dist/webpack.config.dev.js b/dist/webpack.config.dev.js new file mode 100644 index 00000000..994a7dd6 --- /dev/null +++ b/dist/webpack.config.dev.js @@ -0,0 +1,16 @@ +const { merge } = require('webpack-merge'); +const common = require('./webpack.common.js'); + + +module.exports = merge(common, { + mode: 'development', + devtool: 'inline-source-map', + devServer: { + liveReload: true, + hot: true, + open: true, + static: ['./'], + }, +}); + + diff --git a/dist/webpack.config.js b/dist/webpack.config.js deleted file mode 100644 index f40dbd27..00000000 --- a/dist/webpack.config.js +++ /dev/null @@ -1,16 +0,0 @@ -const HtmlWebpackPlugin = require('html-webpack-plugin'); -module.exports = { - mode : 'development', - entry : './js/app.js', - devServer: { - liveReload: true, - hot: true, - open: true, - static: ['./'], - }, - plugins: [ - new HtmlWebpackPlugin({ - template: './index.html' - }) - ] -}; \ No newline at end of file diff --git a/dist/webpack.config.prod.js b/dist/webpack.config.prod.js new file mode 100644 index 00000000..c35245cf --- /dev/null +++ b/dist/webpack.config.prod.js @@ -0,0 +1,28 @@ +const { merge } = require('webpack-merge'); +const common = require('./webpack.common.js'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const CopyPlugin = require('copy-webpack-plugin'); + +module.exports = merge(common, { + mode: 'production', + plugins: [ + new HtmlWebpackPlugin({ + template: './index.html' + }), + new CopyPlugin({ + patterns: [ + { from: 'img', to: 'img' }, + { from: 'css', to: 'css' }, + { from: 'js/vendor', to: 'js/vendor' }, + { from: 'icon.svg', to: 'icon.svg'}, + { from: 'favicon.ico', to: 'favicon.ico'}, + { from: 'tile-wide.png', to: 'tile-wide.png'}, + { from: 'robots.txt', to: 'robots.txt'}, + { from: 'icon.png', to: 'icon.png'}, + { from: '404.html', to: '404.html'}, + { from: 'site.webmanifest', to: 'site.webmanifest'}, + { from: 'tile.png', to: 'tile.png'} + ], + }) + ], +}); \ No newline at end of file diff --git a/docs/usage.md b/docs/usage.md index 87761532..bff4ab2e 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -49,7 +49,9 @@ A basic HTML5 Boilerplate site initially looks something like this: ├── site.webmanifest ├── tile.png ├── tile-wide.png -└── webpack.config.js +└── webpack.common.js +└── webpack.config.dev.js +└── webpack.config.prod.js ``` What follows is a general overview of each major part and how to use them. @@ -106,3 +108,62 @@ Icon with your own. If you want to use different Apple Touch Icons for different resolutions please refer to the [according documentation](extend.md#apple-touch-icons). + +### Webpack + +The project contains a simple [webpack](https://webpack.js.org/) configuration. + +To get started developing a site with a development server, run the following +commands from within the `/dist/` folder in the project's repo or within the +root folder of the dowloaded project files, the folder created by `npm install` +or the project folder created by running [create\-html5\-boilerplate](https://github.com/h5bp/create-html5-boilerplate) + +``` +npm install +npm run start +``` + +This will start a Webpack development server with hot reloading of edited files. + +To package a site for production run + +``` +npm run build +``` + +This command will bundle up the site's JavaScript and copy over static assets to +the newly created `dist` folder. + + +There are three files: + +#### webpack.common.js + +Both the production and development scripts inherit from this common script. + +#### webpack.config.dev.js + +This development configuration defines the behavior of development server. + +#### webpack.config.prod.js + +This production configuration defines the behavior of the production build. + +It copies the following files and folders to the dist folder: + +* css +* img +* js/vendor +* 404.html +* favicon.ico +* icon.png +* icon.svg +* index.html +* robots.txt +* site.webmanifest +* tile.png +* tile-wide.png + +`js/vendor` is copied over in order to allow you to use unprocessed JS files +(like Modernizr) in addition to the files bundled based on the project's entry +point `app.js.` diff --git a/gulpfile.mjs b/gulpfile.mjs index 08c074c5..1c7002c9 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -134,6 +134,7 @@ gulp.task('modernizr', (done) => { gulp.task('lint:js', () => gulp.src([ `${dirs.src}/js/*.js`, + `${dirs.src}/*.js`, `${dirs.test}/*.mjs` ]).pipe(gulpEslint()) .pipe(gulpEslint.failOnError()) diff --git a/package-lock.json b/package-lock.json index 71629ee4..707fe881 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20496,4 +20496,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/package.json b/src/package.json index b3cfb9b8..3357b47a 100644 --- a/src/package.json +++ b/src/package.json @@ -10,12 +10,15 @@ "author": "", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "start": "webpack-dev-server --open --port 8080" + "start": "webpack serve --open --config webpack.config.dev.js", + "build": "webpack --config webpack.config.prod.js" }, "devDependencies": { - "webpack": "^5.74.0", + "copy-webpack-plugin": "^11.0.0", "html-webpack-plugin": "^5.5.0", + "webpack": "^5.74.0", "webpack-cli": "^4.10.0", - "webpack-dev-server": "^4.11.1" + "webpack-dev-server": "^4.11.1", + "webpack-merge": "^5.8.0" } } diff --git a/src/webpack.common.js b/src/webpack.common.js new file mode 100644 index 00000000..18d80c6d --- /dev/null +++ b/src/webpack.common.js @@ -0,0 +1,12 @@ +const path = require('path'); + +module.exports = { + entry: { + app: './js/app.js', + }, + output: { + path: path.resolve(__dirname, 'dist'), + clean: true, + filename: './js/app.js', + }, +}; \ No newline at end of file diff --git a/src/webpack.config.dev.js b/src/webpack.config.dev.js new file mode 100644 index 00000000..994a7dd6 --- /dev/null +++ b/src/webpack.config.dev.js @@ -0,0 +1,16 @@ +const { merge } = require('webpack-merge'); +const common = require('./webpack.common.js'); + + +module.exports = merge(common, { + mode: 'development', + devtool: 'inline-source-map', + devServer: { + liveReload: true, + hot: true, + open: true, + static: ['./'], + }, +}); + + diff --git a/src/webpack.config.js b/src/webpack.config.js deleted file mode 100644 index f40dbd27..00000000 --- a/src/webpack.config.js +++ /dev/null @@ -1,16 +0,0 @@ -const HtmlWebpackPlugin = require('html-webpack-plugin'); -module.exports = { - mode : 'development', - entry : './js/app.js', - devServer: { - liveReload: true, - hot: true, - open: true, - static: ['./'], - }, - plugins: [ - new HtmlWebpackPlugin({ - template: './index.html' - }) - ] -}; \ No newline at end of file diff --git a/src/webpack.config.prod.js b/src/webpack.config.prod.js new file mode 100644 index 00000000..c35245cf --- /dev/null +++ b/src/webpack.config.prod.js @@ -0,0 +1,28 @@ +const { merge } = require('webpack-merge'); +const common = require('./webpack.common.js'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const CopyPlugin = require('copy-webpack-plugin'); + +module.exports = merge(common, { + mode: 'production', + plugins: [ + new HtmlWebpackPlugin({ + template: './index.html' + }), + new CopyPlugin({ + patterns: [ + { from: 'img', to: 'img' }, + { from: 'css', to: 'css' }, + { from: 'js/vendor', to: 'js/vendor' }, + { from: 'icon.svg', to: 'icon.svg'}, + { from: 'favicon.ico', to: 'favicon.ico'}, + { from: 'tile-wide.png', to: 'tile-wide.png'}, + { from: 'robots.txt', to: 'robots.txt'}, + { from: 'icon.png', to: 'icon.png'}, + { from: '404.html', to: '404.html'}, + { from: 'site.webmanifest', to: 'site.webmanifest'}, + { from: 'tile.png', to: 'tile.png'} + ], + }) + ], +}); \ No newline at end of file diff --git a/test/file_existence.mjs b/test/file_existence.mjs index 0fae66fa..0f87f6ee 100644 --- a/test/file_existence.mjs +++ b/test/file_existence.mjs @@ -18,8 +18,11 @@ const expectedFilesInDistDir = [ '.gitignore', '404.html', 'package.json', - 'webpack.config.js', + 'webpack.common.js', + 'webpack.config.dev.js', + 'webpack.config.prod.js', + 'css/', // for directories, a `/` character // should be included at the end 'css/normalize.css',