Skip to content

Commit

Permalink
v1.3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
goldingdamien committed Jun 14, 2022
1 parent 1096a44 commit 18523ca
Show file tree
Hide file tree
Showing 3 changed files with 272 additions and 544 deletions.
136 changes: 117 additions & 19 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,50 @@
const webpack = require('webpack')
const minify = require('html-minifier').minify
const csso = require('csso')
// ONLY Node.js dependencies at top.
// Keep dependencies to a minimum. Add dependencies if required for the functions you use.
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')

// const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); // Archived. Use:
// https://github.com/webpack-contrib/terser-webpack-plugin
const TerserPlugin = require('terser-webpack-plugin'); // Included with webpack 4.
function webpack() {
return require('webpack')
}

function minimize() {
// Minimizing
// const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); // Archived. Use:
// https://github.com/webpack-contrib/terser-webpack-plugin
/*
Webpack v5 comes with the latest terser-webpack-plugin out of the box.
If you are using Webpack v5 or above and wish to customize the options, you will still need to install terser-webpack-plugin.
Using Webpack v4, you have to install terser-webpack-plugin v4.
*/
const TerserPlugin = require('terser-webpack-plugin'); // Included with webpack 4.
return TerserPlugin
}

/**
* Get dependencies from here to prevent needing to install all.
*/
function getDependencies() {
return {
htmlMinifier: () => {
const { minify } = require('html-minifier')
return minify
},
csso: () => {
const csso = require('csso')
return csso
}
}
}

/**
* @see https://webpack.js.org/configuration/module/#rule
*/
const Rules = {
json: () => {
// THIS IS NO LONGER REQUIRED. IN-BUILT IN NEWER VERSIONS OF WEBPACK.
},
/**
* https://github.com/webpack-contrib/raw-loader
*/
htmlString: () => {
return {
test: /\.html$/,
Expand All @@ -21,6 +53,10 @@ const Rules = {
]
}
},
/**
* https://github.com/gajus/to-string-loader
* https://github.com/webpack-contrib/css-loader
*/
cssString: () => {
return {
test: /\.css$/,
Expand All @@ -30,6 +66,9 @@ const Rules = {
]
}
},
/**
* https://github.com/webpack-contrib/file-loader
*/
image: () => {
return {
test: /\.(jpe?g|png|gif|svg)$/i,
Expand Down Expand Up @@ -67,12 +106,61 @@ const Rules = {
}
}

/**
* General helpers for things like conversions.
* Use "WebpackRecipes" for getting presets, etc.
*/
class Helpers {
/*
Migration info:
v1 => v2/v3: https://webpack.js.org/migrate/3/
v3 => v4: https://webpack.js.org/migrate/4/
v4 => v5: https://github.com/webpack/changelog-v5/blob/master/MIGRATION%20GUIDE.md
*/

/**
* @param {(import('webpack').RuleSetRule) | "..." | any} rule
*/
static modernizeWebpackRule(rule) {
if (rule.loaders) {
rule.use = rule.loaders
delete rule.loaders
}
if (rule.loader) {
rule.use = {
loader: rule.loader
}
delete rule.loader
if (rule.options) {
rule.use.options = rule.options
delete rule.options
}
}
}

/**
*
* @param {import('webpack').Configuration} config
*/
static modernizeConfig(config) {
if (config.module && config.module.rules) {
config.module.rules.forEach(Helpers.modernizeWebpackRule)
}
}
}

/**
* Use "common" for default configuration. Example: .common(__dirname)
*/
class WebpackRecipes {
/**
* @example .common(__dirname) // If executing form root with webpack.config.js in root directory.
* @param {string} dirname Currently required. SHOULD make unnecessary in the future.
* @param {{ mode?: 'development'|'production' }} [options]
*/
static common(dirname) {
const mode = WebpackRecipes.getWebpackMode()
static common(dirname, options = {}) {
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const mode = options.mode || WebpackRecipes.getWebpackMode()

return /** @type { import('webpack').Configuration } */ ({
mode,
Expand All @@ -85,12 +173,17 @@ class WebpackRecipes {
},
plugins: [
...(mode === 'production' ? [
// CleanWebpackPlugin can be replaced with output: { clean: true }
// https://stackoverflow.com/a/66675975/1764521
new CleanWebpackPlugin()
] : []),
]
})
}

/**
* @see https://webpack.js.org/configuration/mode/
*/
static getWebpackMode() {
return getWebpackMode()
}
Expand Down Expand Up @@ -144,18 +237,18 @@ class WebpackRecipes {

/**
* @param {('indexHTML'|'css'|'img'|'CHANGELOG')[]} patterns
* @returns
* @param {string} dirname
*/
static copyWebpackPluginPatterns(patterns = []) {
static copyWebpackPluginPatterns(patterns = [], dirname) {
/**
* @typedef {{ toString: () => string }} Content
*/

const map = {
indexHTML: () => ({ from: 'index.html', transform: /** @param {Content} content */ (content) => minify(content.toString()) }), // { from: 'index.html' },
css: () => ({ from: path.resolve(__dirname, 'css'), to: 'css', transform: /** @param {Content} content */ (content) => csso.minify(content.toString()).css }),
img: () => ({ from: path.resolve(__dirname, 'img'), to: 'img' }),
CHANGELOG: () => ({ from: path.resolve(__dirname, 'CHANGELOG.md') })
indexHTML: () => ({ from: 'index.html', transform: /** @param {Content} content */ (content) => getDependencies().htmlMinifier()(content.toString()) }), // { from: 'index.html' },
css: () => ({ from: path.resolve(dirname, 'css'), to: 'css', transform: /** @param {Content} content */ (content) => getDependencies().csso().minify(content.toString()).css }),
img: () => ({ from: path.resolve(dirname, 'img'), to: 'img' }),
CHANGELOG: () => ({ from: path.resolve(dirname, 'CHANGELOG.md') })
}

return patterns.map(pattern => map[pattern]())
Expand All @@ -177,7 +270,7 @@ class WebpackRecipes {
},
}),
*/
new TerserPlugin({
new (minimize())({
terserOptions: {
compress: {
drop_console: true
Expand All @@ -196,7 +289,7 @@ class WebpackRecipes {
return {
optimization: {
minimizer: [
new TerserPlugin({
new (minimize())({
terserOptions: {
compress: {
drop_console: true,
Expand All @@ -212,6 +305,9 @@ class WebpackRecipes {
/**
* Each function SHOULD be grouped.
* mode: Is still allowed because of legacy dependencies.
*
* For quick usage: Use the example:
* @example module.exports = WebpackHelpers.Recipes.common(__dirname);
*/
const WebpackHelpers = {
mode: () => {
Expand Down Expand Up @@ -242,18 +338,20 @@ const WebpackHelpers = {
return mode
},
Recipes: WebpackRecipes,
Helpers,
Rules,
Plugins: {
jquery: () => {
// Use the ProvidePlugin constructor to inject jquery implicit globals
return new webpack.ProvidePlugin({
return new (webpack()).ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': "jquery'",
'window.$': 'jquery'
})
},
bundleAnalyzer: () => {
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
// https://github.com/webpack-contrib/webpack-bundle-analyzer
return new BundleAnalyzerPlugin({
analyzerMode: 'static'
Expand Down
Loading

0 comments on commit 18523ca

Please sign in to comment.