@siteone/webpack-config
v3.2.0
Published
SiteOne webpack config for server generated sites
Downloads
206
Keywords
Readme
SiteOne Webpack 5 config
This package contains basic webpack configuration for server-generated websites (it is not meant to be used for SPAs). It works best with Craft CMS and twigpack plugin, but it could be used with almost any type of BE frameworks/CMS like wordpress or nette. We don't provide a way how to load your assets in your templates. For Craft CMS we are using twigpack plugin, other than that it's up to you. You can simply use script/style tag or create some automatic solution that parses your manifest.json file and inserts your tags for you.
The goal is to provides webpack configuration that can be updated and maintained from one place and used on multiple projects. It provide basic config that can be used only partially or/and extended to fit your project needs.
It is inspired by nystudio107/annotated-webpack-config and it can be used with Twigpack plugin for Craft CMS
Installation
yarn add webpack webpack-cli @babel/core @siteone/webpack-config --dev
OR
npm install webpack webpack-cli @babel/core @siteone/webpack-config --save-dev
Basic Example
Create webpack.common.js
const {
buildWebpackConfig,
createConfigFunctions,
} = require("@siteone/webpack-config");
const settings = {
js: {
entries: {
test: "./templates/_modules/test/test.js",
},
output: {
path: path.resolve(__dirname, "./web/dist/"),
},
},
};
const configFunctions = [
// Common
createConfigFunctions.createCommonConfig,
createConfigFunctions.createManifestConfig,
// Scss
createConfigFunctions.createMiniCssExtractConfig,
createConfigFunctions.createCssLoaderConfig,
createConfigFunctions.createPostCssLoaderConfig,
createConfigFunctions.createSassLoaderConfig,
// JS
createConfigFunctions.createBabelLoaderConfig,
];
const webpackModernProdConfig = buildWebpackConfig(
settings,
configFunctions,
"production"
);
Features
Composition
This configuration is split into small blocks that contain configuration only for a certain plugin, loader, etc. With this approach, you can decide to use or omit any part.
For example, there are separate configurations for:
- cssLoader
- sassLoader
- postCss
So you can decide if you would like to use postCss, Sass, or just simple CSS with no further processing. Every part of this configuration export createConfig function. It accepts settings object and returns partial of webpack configuration object.
Example:
createSassLoaderConfig = (settings) => {
return {
module: {
rules: [
{
test: /\.scss$/,
use: ["sass-loader"],
},
],
},
};
};
These partials are then merged with webpack-merge plugin.
const webpackConfig = merge(
// other createConfig functions
createMiniCssExtractConfig(settings),
createCssLoaderConfig(settings),
createPostCssLoaderConfig(settings),
createBabelLoaderConfig(settings)
);
This allows you to add your createConfig function and extend your configuration. Or omit any function you don't want to use.
Legacy and modern mode
Inspired by nystudio107/annotated-webpack-config you can exploit the configuration object to create more different webpack configs.
This means we provide two default configurations. Other than that it's up to you which features you would like to use in each mode.
The difference is that legacy config contains other browserslist than modern and this way you can build modern and legacy assets then distribute these assets to different browsers. So old browsers should still work but bundle for modern browsers doesn't have to be compiled to old js. This way you can save some bundle size.
API
buildWebpackConfig(userSettings, createConfigFunctions, webpackMode, [type])
Creates a webpack config based on the given configuration and createConfig functions.
Arguments
userSettings
(Object): Partial of settings object
Settings:
| key | type | Default (modern/legacy) | Description | | --------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | | assets | object | see below | | | assets.filename | string | "assets/[hash][ext][query]" | webpack custom output filename | | js | object | see below | | | js.browserslist | array | ["> 1%", "last 2 versions", "Firefox ESR"] / [ "last 2 Chrome versions", "not Chrome < 60", "last 2 Safari versions", "not Safari < 10.1", "last 2 iOS versions", "not iOS < 10.3", "last 2 Firefox versions", "not Firefox < 54", "last 2 Edge versions", "not Edge < 15", ] | browserslist array definition | | js.output | object | see below | | | js.output.path | string | "./web/dist/" | webpack output.path | | js.output.publicPath | string | "/dist/" | webpack output.publicPath | | js.output.filename | string | "[name].[contenthash].js" / "[name]-legacy.[contenthash].js" | webpack output.filename | | js.entries | string | object | null | webpack entry | | css | object | see below | | | css.browserslist | array | ["> 1%", "last 2 versions", "Firefox ESR"] | browserslist array definition | | css.filename | string | "[name].[contenthash].css" | minicssextract filename | | css.sassLoaderOptions | object | {} | webpack sass-loader options | | devServer | object | see below | | | devServer.port | number | 8080 | webpack dev-server port | | devServer.host | string | localhost | webpack dev-server host | | devServer.https | boolean | false | webpack dev-server https | | devServer.contentBase | string | "./templates", | webpack dev-server contentBase | | devServer.public | string | null | webpack dev-server public | | devServer.publicPath | string | null | webpack dev-server publicPath | | devServer.sockHost | string | null | webpack dev-server sockHost | | resolve | object | see below | | | resolve.aliases | object | {} | webpack resolve.alias | | resolve.extensions | array | [] | webpack resolve.extensions |
createConfigFunctions
(array): Array of createConfig functions. Order matters.webpackMode
(string): Webpack mode[type]
("modern" | "legacy"): Default is "modern". Determinate which default settings are loaded and merged with youruserSettings
Returns
(Object): Returns an object corresponding to partials returned by provided creteConfigFunctions merged together and combined with settings. It should be partial of webpack config (not validated though).
Example
const {
buildWebpackConfig,
createConfigFunctions,
} = require("@siteone/webpack-config");
const settings = {
js: {
entries: {
test: "./templates/_modules/test/test.js",
},
output: {
path: path.resolve(__dirname, "./web/dist/"),
},
},
};
const configFunctions = [
// Common
createConfigFunctions.createCommonConfig,
createConfigFunctions.createManifestConfig,
createConfigFunctions.createAssetsConfig,
createConfigFunctions.createOptimizationConfig,
// Scss
createConfigFunctions.createMiniCssExtractConfig,
createConfigFunctions.createCssLoaderConfig,
createConfigFunctions.createPostCssLoaderConfig,
createConfigFunctions.createSassLoaderConfig,
createConfigFunctions.createCssMinimizerConfig,
// JS
createConfigFunctions.createBabelLoaderConfig,
];
const webpackModernProdConfig = buildWebpackConfig(
settings,
configFunctions,
"production"
);
// Config with added dev server configuration
const webpackModernDevConfig = buildWebpackConfig(
modernSettings,
[createConfigFunctions.createDevServerConfig, ...configFunctions],
"development"
);
type createConfig(settings)
The whole configuration is created by these createConfig functions that accept settings object and returns partial of webpack config, that is later merged together in a specified order.
Arguments
settings
(object): Settings object read more in buildWebpackConfig section.
Reurns
(object): Return a partial of webpack config object.
Example
const createBabelLoaderConfig = (settings) => {
return {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
cacheDirectory: true,
sourceType: "unambiguous",
presets: [
[
"@babel/preset-env",
{
modules: false,
corejs: {
version: 2,
proposals: true,
},
useBuiltIns: "usage",
targets: {
browsers: settings.js.browserslist,
},
},
],
],
plugins: [
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-transform-runtime",
],
},
},
},
],
},
};
};
Tip
- You can add your custom settings in the settings object
- You can create your own set of createConfig functions and save it to your custom package and then use it together with this package
Using with Twigpack
Like it was mentioned before this package was created to be used with Craft CMS and Twigpack plugin. Twigpack takes care of loading assets to your templates, cache busting, etc.
Basic example
package.json
"scripts": {
"build": "webpack --config webpack.prod.js --progress",
"dev": "webpack serve --config webpack.dev.js"
},
webpack.common.js - this is where your config lives
const path = require("path");
const {
buildWebpackConfig,
createConfigFunctions,
} = require("@siteone/webpack-config");
const commonSettings = {
js: {
entries: {
test: "./templates/_modules/test/test.js",
},
output: {
path: path.resolve(__dirname, "./web/dist/"),
},
},
};
const modernSettings = {
...commonSettings,
};
const legacySettings = {
...commonSettings,
};
const commonConfigFunctions = [
// Common
createConfigFunctions.createCommonConfig,
createConfigFunctions.createManifestConfig,
createConfigFunctions.createAssetsConfig,
createConfigFunctions.createOptimizationConfig,
// Scss
createConfigFunctions.createMiniCssExtractConfig,
createConfigFunctions.createCssLoaderConfig,
createConfigFunctions.createPostCssLoaderConfig,
createConfigFunctions.createSassLoaderConfig,
createConfigFunctions.createCssMinimizerConfig,
// JS
createConfigFunctions.createBabelLoaderConfig,
];
const webpackModernProdConfig = buildWebpackConfig(
modernSettings,
commonConfigFunctions,
"production"
);
const webpackLegacyProdConfig = buildWebpackConfig(
legacySettings,
commonConfigFunctions,
"production",
"legacy"
);
const webpackModernDevConfig = buildWebpackConfig(
modernSettings,
[createConfigFunctions.createDevServerConfig, ...commonConfigFunctions],
"development"
);
module.exports = {
webpackModernProdConfig,
webpackLegacyProdConfig,
webpackModernDevConfig,
};
webpack.dev.js
const { webpackModernDevConfig } = require("./webpack.common");
module.exports = webpackModernDevConfig;
webpack.prod.js
const {
webpackModernProdConfig,
webpackLegacyProdConfig,
} = require("./webpack.common");
module.exports = [webpackModernProdConfig, webpackLegacyProdConfig];
const {
webpackModernProdConfig,
webpackLegacyProdConfig,
} = require("./webpack.common");
module.exports = [webpackModernProdConfig, webpackLegacyProdConfig];
twigpack.php
return [
'*' => [
'manifest' => [
'legacy' => 'manifest-legacy.json',
'modern' => 'manifest.json',
],
'server' => [
'manifestPath' => '@webroot/dist/',
'publicPath' => '/',
],
'devServer' => [
'manifestPath' => 'http://localhost:8080/dist',
'publicPath' => 'http://localhost:8080/',
],
]
];
This config doesn't support critical CSS generated by webpack. In our opinion, it doesn't make sense as it needs running compiled copy of your website and it doesn't exist at build time. So it's up to you to create some script to generate your critical CSS files. We recommend critical js library.