webpack-toolbox v1.0.15
webpack-toolbox
Collection of preconfigured wellcrafted webpack loaders and plugins, exposed in a functional way. You should be familair with webpack to understand the concepts explained below.
summary
Creating a webpack config
file and configuring the toolchain of loaders
and plugins
can be a daunting task.
This toolbox acceleraties the process by:
- Installing the modules used by the toolbox (typescript, tslint, postcss, etc)
- Providing a easy to use snippets to insert in yout webpack configuration file.
Installaton
Webpack toolbox installs a lot of modules and other tools, so it can take some time.
npm i --save-dev webpack-toolbox
Table of Contents
Configuration file
Webpack expects as configuration input a javascript object (or a function returning this object). The webpack-toolbox has a palette of functions to create parts of this configuration object.
A typical webpack configuration (config.js
) file using webpack-toolbox would look like this:
const {
external: { wPackN_Ext },
rule: { lint, tsc },
plugins: { rm },
resolve: { extentions }
} = require('webpack-toolbox');
const { resolve } = require('path');
module.exports = function(env) {
return [{
target: "node",
entry: {
myLib: resolve('src/lib/index.ts'),
'myLib.min': resolve('src/lib/index.ts')
},
output: {
path: resolve('dist'),
filename: '[name].js',
libraryTarget: 'umd2',
library: 'MYLIB'
},
devtool: 'source-map',
externals: [
wPackN_Ext()
],
module: {
rules: [
lint(),
tsc({ declaration: true })
]
},
plugins: [
rm({ paths: ['lib', './'] })
],
resolve: {
extensions,
},
}];
}
- for
config.externals
see § External snippets. - for
config.module.rules
see § Rule snippets.- To create your own rules with loaders from webpack-toolkit see § pets.
- for
config.plugins
see § Plugin snippets. - for
config.resolve
see § Resolve snippets.
pets
The webpack config file doesnt use loaders directly it wraps them into rules. In case the provided rules in the toolkit do not suffice you can build your own rules with these loader snippets.
file
This function configures the options
of the file-loader
.
const { file } = require('webpack-toolbox').loader;
const opt = {} // specify options for 'file-loader'
const fl1 = file(opt); // merges options with default
const fl2 = file(); // uses default options { name: '[name].[ext]' }
/* =>
{
loader: 'file-loader',
options:
<opt> merged with
{ name: '[name].[ext]' }
}
*/
asString
This function returns the raw-loader
config snippet.
The raw-loader
returns any file as a string.
It has no options.
const { asString } = require('webpack-toolbox').loader;
const str = asString();
/* =>
{
loader: 'raw-loader'
}
*/
scss
This function configures options for the sass-loader
.
The sass-loader
transpiles an scss
file to css
.
Usage:
const { loader: { scss } } = require('webpack-toolbox');
const opt = {}; //specifiy options here
const sc1 = scss(opt);
const sc2 = scss(); // go with default
/* =>
{
loader: 'sass-loader',
options:
<opt> merged with
{
sourceMap: uid(32),
precision: 5
}
}
*/
cssDependencies
This function configures options for the css-loader
.
The css-loader
resolves the 'import' statement in css
files.
Usage:
const { loader: { cssDependencies } } = require('webpack-toolbox');
const opt = { url: false}; //specify or override options here
const css1 = cssDependencies(opt); // merge opt with default
const css2 = cssDependencies(); // go with default , see below
/*=>
{
loader: 'css-loader',
options: {
url: true,
import: true,
modules: true,
minimize: false,
sourceMap: true,
camelCase: false,
localIdentName: '[local]_[path][name]',
importLoaders: 2
}
}
*/
postCss
This function configures options for the postcss-loader
.
The postcss-loader
performs a number of transpilations on css
files via postcss-loader
plugins.
Usage:
const { loader: { postCss } } = require('webpack-toolbox');
const opt = {}; //specifiy options here
const css1 = postCss(opt); //merges opt with default
const css2 = postCss(); //Go with default only , see below
/*
{
loader: 'postcss-loader',
options: {
plugins: {
postcss-preset-env':{
stage: 3,
browsers: 'last 2 versions',
features:{
'nesting-rules': true
}
},
autoprefixer: {},
'postcss-sorting': {
'properties-order': 'alphabetical'
}
},
sourceMap: true
}
}
}
*/
embedCss
TODO:
This function configures options for the style-loader
.
TODO: check the dock what is the diff with "textextractor".
The style-loader
inserts css in the html form via <style>
tags.
Usage:
const { loader: { embedCss } } = require('webpack-toolbox');
const opt = {}; //specifiy options here
const emb1 = embedCss(opt); //merges opt with default
const emb2 = embedCss(); // go with default only , see below
/*==>
{
loader: 'style-loader',
options:
<opt> is merged with
{
sourceMap: true
}
}
*/
tslint
This function configures options for the tslint-loader
.
The tslint-loader
validates (and optionally fixes) code styling.
Apply the tslint loader as preLoader in your webpack configuration.
Notes:
- :warning: this loader has severe performance problems since mid 2017 issue.
- --prefix is depricated, use --project instead see note.
Usage:
const { resolve } = require('path');
const { loader: { tsl } } = require('webpack-toolbox');
const opt = {
configFile: resolve('my_tsconfig_test.json') ,
emitErrors: false,
};
const t1 = tsl(opt); //merges opt with default
const t2 = tsl();// just use default, see below
/*==>
loader: 'tslint-loader',',
options:
<opt> merged with
configFile: resolve('tslint.json'),
emitErrors: true,
failOnHint: true,
fix: true,
tsConfigFile: resolve('tsconfig.webpack.json')
*/
tsl
This function configures options for the ts-loader
.
The ts-loader
transpiles typscript files to javascript.
Note: the configFile
(points to tsconfig.json
) property of the options
object is default set to <project working directory>/tsconfig.webpack.json
decl
declare function tsl(loaderOptions): {...}
const { resolve } = require('path');
const { loader: { tsl } } = require('webpack-toolbox');
const opt = { configFile: resolve('tsconfig_test.json') };
const t1 = tsl(opt); //merges opt with default
const t2 = tsl(); //go with default only , see "options" below
/*==>
{
loader: 'ts-loader',
options:
<opt> merged with
{
transpileOnly: false,
happyPackMode: false, //set this to true later, see doc,
logInfoToStdOut: true, //stderr to stdout
configFile: resolve('tsconfig.webpack.json'),
}
}
*/
Rule snippets
Rules are matched to requests when modules are created. For all the configuration options for webpack rules
see module.rule doc. Rules apply loaders to transform files (modules).
tsc
This function creates a webpack Object configuration snippet for transpilation of typescript source files.
tsc
configures the loader tsl
.
decl
function tsc(loaderOptions, ruleOptions): {..};
loaderOptions
are passed directly to thetsc
function.ruleOptions
configure the specific webpack rule- property
Rule.test
is fixed and set to/\.ts$/i
. - property
Rule.use
is fixed and set to the result of the functiontsl(loaderOptions)
.
- property
Usage:
const wbtk = require('webpack-toolkit');
const { rule: { tsc } } = wbtk;
const loaderOptions = {}; // go with defaults
const ruleOptions = {}; // got with defaults
const rule1 = tsc(
loaderOptions, /* loader options, passed directly to `tsl`*/
ruleOptions, /* define module.rule properties */
);
/*=>
{
test: /\.ts$/i,
use: {
transpileOnly: false,
happyPackMode: false, //set this to true later, see doc,
logInfoToStdOut: true, //stderr to stdout
configFile: resolve('tsconfig.webpack.json'),
}
}
*/
sql
This function creates a webpack Object configuration snippet for the loading the text of an sql file as a string in your source code.
sql
configures the loader asString
.
decl
function sql(ruleOptions): {..};
ruleOptions
configure the specific webpack rule- property
Rule.test
is fixed and set to/\.ts$/i
. - property
Rule.use
is fixed and set to the result of the functionasString()
.
- property
Usage:
const wbtk = require('webpack-toolkit');
const { rule: { sql } } = wbtk;
const ruleOptions = { issuer: 'index.js' };
const rule1 = sql(
ruleOptions /* define module.rule properties */
);
/*=>
{
test: /\.sql$/i,
use: asString(),
issuer: 'index.js'
}
*/
gql
This function creates a webpack Object configuration snippet for the loading the text of an gql file (GraphQL) as a string in your source code.
gql
configures the loader asString
.
decl
function gql(ruleOptions): {..};
ruleOptions
configure the specific webpack rule- property
Rule.test
is fixed and set to/\.gql$/i
. - property
Rule.use
is fixed and set to the result of the functionasString()
.
- property
Usage:
const wbtk = require('webpack-toolkit');
const { rule: { gql } } = wbtk;
const ruleOptions = { resourceQuery: /inline/ };
const rule1 = gql(
ruleOptions /* define module.rule properties */
);
/*=>
{
test: /\.gql$/i,
use: asString(),
resourceQuery: /inline/
}
*/
fonts
This function creates a webpack Object configuration snippet for emitting a font file via the file-loader
. Either emit the the font file, it into the bundle or reference it via an url.
decl
function fonts(loaderOptions, ruleOptions): {..};
loaderOptions
are passed directly to thefile
function.ruleOptions
configure the specific webpack rule- property
Rule.test
is fixed and set to/\.ts$/i
. - property
Rule.use
is fixed and set to the result of the functionfile(loaderOptions)
.
- property
Usage:
const wbtk = require('webpack-toolkit');
const { rule: { fonts } } = wbtk;
const loaderOptions = { emitfile: true }; //emit the fontfile with the bundle
const ruleOptions = { resourceQuery: /inline/ };
const rule1 = fonts(
loaderOptions,
ruleOptions
);
/*=>
{
test: /(\.svg|\.woff|\.woff2|\.[ot]tf|\.eot)$/,
use: // result of file( { emitFile: true } )
{
loader: 'file-loader',
options:{
name: '[name].[ext]',
emitfile: true
}
}
resourceQuery: /inline/
}
*/
emitJsCss
This function creates a webpack Object configuration snippet for emitting a css/js file that will not be part of the bundle (for example 3rd party vendor). It uses the file-loader
.
require
-ing the file in your js file will return the uri of the css/js file.
decl
function emitJsCss(loaderOptions, ruleOptions): {..};
loaderOptions
are passed directly to thefile
function.ruleOptions
configure the specific webpack rule- property
Rule.test
is fixed and set to/\.(js|css)$/
. - property
Rule.include
is determined by the value ofruleOptions.include
(see table below): - property
Rule.use
is fixed and set to the result of the functionfile(loaderOptions)
.
- property
Usage:
const wbtk = require('webpack-toolkit');
const { resolve } = require('path');
const { rule: { emitJsCss } } = wbtk;
const loaderOptions = { emitfile: true }; //emit the fontfile with the bundle
const ruleOptions = { include: [ resolve('src/vendor/d3'), resolve('src/vendor/react-dom') ] };
const rule1 = emitJsCss(
loaderOptions,
ruleOptions
);
/* =>
{
test: /\.(js|css)$/
include: ['src/vendor/d3', 'src/vendor/react-dom' ]
use: {
loader: 'file-loader',
options:{
name: '[name].[ext]',
emitfile: true
}
}
}
*/
embedSqlGql
This function creates a webpack Object configuration snippet for embedding an sql/gql file that will be loaded into the final bundle with require
. It uses the raw-loader
via asString
.
decl
function embedSqlGql(ruleOptions): {..};
ruleOptions
configure the specific webpack rule- property
Rule.test
is fixed and set to/\.([sg]ql)$/
. - property
Rule.use
is fixed and set to the result of the functionasString()
.
- property
Usage:
const wbtk = require('webpack-toolkit');
const { resolve } = require('path');
const { rule: { embedSqlGql } } = wbtk;
const ruleOptions = { include: [ resolve('src/vendor/d3'), resolve('src/vendor/react-dom') ] };
const rule1 = embedSqlGql( ruleOptions );
/* =>
{
test: /\.([sg]ql)$/,
include: ['src/vendor/d3', 'src/vendor/react-dom' ]
use: {
loader: 'raw-loader'
}
}
*/
cssFiles
Function to provide a rule to transpile scss/sass files to css files. Combines 4 loader-snippet generating functions: 1) embedCss
, 2) cssDependencies
, 3) postcss
, 4) scss
.
decl
function cssFiles(ruleOptions): {..};
Because cssFiles
configures several loaders and the rule itself, the "options" are partitioned into several subobjects:
declare type ruleOptions {
embed: {...}, // for embedCss(embed)
depend: {...}, // for cssDependencies(depend)
post: {...}, // for postCss(post)
oscss: {...} // for scss(oscss)
rule: {...} // contains options for this rule
}
ruleOptions.embed
: options for embedCss.ruleOptions.depend
: options for cssDependencies.ruleOptions.post
: options for postCss.ruleOptions.scss
: options for scss.ruleOptions.rule
: options for this rule itself, see webpack rule.
This rule will always have these unchangable properties fixed:
- property
Rule.test
is fixed and set to[/\.s[ca]ss$/, /\.css$/]
. - property
Rule.use
is fixed and is an array of the result of the functionsembedCss
,cssDependencies
,postcss
, andscss
.
Usage:
const wbtk = require('webpack-toolkit');
const { resolve } = require('path');
const { rule: { cssFiles } } = wbtk;
const ruleOptions = {
embed: { sourceMap: true },
depend: { camelCase: false, },
post: {
plugins:
'postcss-sorting': {
'properties-order': 'alphabetical'
}
}
},
scss:{},// go with defaults
rule: {
include: [ resolve('src/vendor/d3'), resolve('src/vendor/react-dom') ] };
}
}
const rule = cssFiles( ruleOptions );
/* =>
{
include: [ resolve('src/vendor/d3'), resolve('src/vendor/react-dom') ] },
test: [/\.s[ca]ss$/, /\.css$/],
use: [
{ //embedCss
loader: 'style-loader',
options: { sourceMap: true }
},
{ //depend
loader: 'css-loader'',
options: { camelCase: false, }
},
{ //post
loader:'postcss-loader',
options:{
plugins: {
'postcss-sorting': {
'properties-order': 'alphabetical'
}
}
}
},
{ //scss
loader: 'sass-loader',
options: {
sourceMap: uid(32),
precision: 5
}
}
]
}
*/
tslinter
This function creates a rule snippet to check typescript source code using the tslint
loader-snippet generating function.
decl
function tslinter(loaderOptions, ruleOptions): {...};
loaderOptions
are passed directly to thetslint
function.- property
typecheck
is always set to false.
- property
ruleOptions
configure the specific webpack rule- property
Rule.test
is fixed and set to/\.tsx?$/
. - property
Rule.use
is fixed and set to the result of the functiontslint(loaderOptions)
. - property
Rule.enforce
is fixed and set to the value"pre"
.
- property
const wbtk = require('webpack-toolkit');
const { rule: { tslinter } } = wbtk;
const ruleOptions = {};
const loaderOptions = {};
const rule = tslinter( loaderOptions, ruleOptions );
/*=>
{
enforce: 'pre',
test: /\.tsx?$/,
use: {
loader: 'tslint-loader',
options: {
typeCheck: false,
configFile: // by default, a "module internal" tslint.json is used,
emitErrors: true,
failOnHint: true,
fix: true,
tsConfigFile: // by default, a "module internal" tsconfig.json is used.
}
}
}
*/
Plugin snippets
These functions create configuration snippets, one for the plugin part of webpack config file.
extractText
This function will returns a configuration snippets for to plugin plugin-extract-text-webpack.
The plugin-extract-text-webpack extracts text (for example css) from the final bundle into a seperate file (handy for parallel loading).
To use this plugin you need to configure the plugin itself of course and also a rule referencing the plugin.
Hence this function's sole option
argument is partitioned into 2 parts: rule
and plugin
.
decl
declare function extractText(options: { rule:{...}, plugin:{...} }) : { rule: {...}, plugin: {...} };
on input:
options
argument object has 2 parts (properties):
plugin
: options for this plugin see extract-text-webpack.plugin.filename
: will default tostyles.css
if not specified.
rule
: options to configure the rule snippet.rule.test
: will default to/\.css$/
if not specified.rule.loaders
: an array of loaders for the extract-text-webpack to use. Defaults to['css-loader', 'postcss-loader']
.
on output:
The returned value from extractText
mirrors its input:
plugin
: the plugin element that needs to be added to the plugin part of the config.rule
: A rule snippet that must be added to the rule part of the config.
Usage:
const wbtk = require('webpack-toolkit');
const { plugin: { extractText } } = wbtk;
const options = {
plugin: {
filename: 'mystyle.css'
}
rule: {} // go with defaults
};
const confextrText = extractText(options); // default is 'extract-text-webpack-plugin'
/*=>
plugin: result of "new ExtractTextPlugin( { filename: 'mystyle.css' })"
rule: {
test: /\.css$,
rule: ExtractTextPlugin.extract(['css-loader', 'postcss-loader'])
}
*/
// incomplete webpack config object
module.exports = {
.
.
module: {
rules: [ confextrText.rule, /* other rules */ ]
}
.
.
plugins: [
confextrText.plugin, /* other plugins */
]
};
miniCssExtract
This function creates a plugin snippet that extracts CSS into separate files. It creates a CSS file per JS file which contains CSS. It supports On-Demand-Loading of CSS and SourceMaps.
It builds on top of a new webpack v4 feature (module types).
Compared to the extractText
( aka extract-text-webpack-plugin )
- Async loading
- No duplicate compilation (performance)
- Easier to use
- Specific to CSS
decl
declare function miniCssExtract(options: { rule:{...}, plugin:{...} }) : { rule: {...}, plugin: {...} };
on input:
options
argument object has 2 parts (properties):
plugin
: options for this plugin see mini-css-extract-plugin.plugin.filename
: will default to[name].[hash].css
if not specified.plugin.chunkFilename
: will default to'[id].[hash].css'
if not specified.
rule
: options to configure the rule snippet.rule.test
: will default to/\.(sa|sc|c)ss$/
if not specified.rule.loaders
: an array of loaders will be merged to get the result array[MiniCssExtractPlugin.loader, ...rule.loaders]
on output:
The returned value from miniCssExtract
mirrors its input:
plugin
: the plugin element that needs to be added to the plugin part of the config.rule
: A rule snippet that must be added to the rule part of the config.
Usage:
const wbtk = require('webpack-toolkit');
const { plugin: { miniCssExtract } } = wbtk;
const options = {
plugin: {
filename: '[name].css'
}
rule: {
loaders:['css-loader']
} // go with defaults
};
const confextrText = miniCssExtract(options);
/*=>
{
plugin: new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
,
rule: {
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader"
]
}
}
*/
// incomplete webpack config object
module.exports = {
.
.
module: {
rules: [ confextrText.rule, /* other rules */ ]
}
.
.
plugins: [
confextrText.plugin, /* other plugins */
]
};
rm
Mirrors unix rm
shell command. This function creates a plugin snippets removing/deleting your build folder(s). This function configures the uses the clean-webpack-plugin
.
decl
declare function rm(options): {...};
on input
options
options for theclean-webpack-plugin
.- property
options.paths
: array of 1 or more paths that needs to be deleted - property
options.root
: defaults to<projectdir>/dist
if root is not specified in options. property
options.*
(*
is wildcard property other thenpaths
in "1.") are passed to theclean-webpack-plugin
- property
on output
returns a snippet for the config.plugin
section of the webpack plugin.
Usage:
const wbtk = require('webpack-toolkit');
const { plugin: { rm } } = wbtk;
const options = {
path: 'dist',
// Write logs to console.
verbose: true,
// Use boolean "true" to test/emulate delete. (will not remove files).
// Default: false - remove files
dry: false
};
const cleanPluginSnippet = rm(options);
/*=>
new CleanWebpackPlugin( 'dist', { verbose: true, dry: false });
*/
module.exports = {
plugins: [
cleanPluginSnippet, /*... other plugins */
]
};
defines
This function will returns a configuration snippet for to plugin webpack.DefinePlugin.
The plugin works much like C language #define
, replacing strings in code before "transpiling" (compiling in C context).
decl
declare function defines( options ): {...}
options
is a JS object with key/value mapping, it will search the sourcefiles for the key
string and replace it with the value
string
Usage:
const wbtk = require('webpack-toolkit');
const { plugin: { defines } } = wbtk;
const options = {
PRODUCTION: JSON.stringify(true),
VERSION: JSON.stringify('5fa3b9'),
BROWSER_SUPPORTS_HTML5: true,
};
const defineSnippet = defines(options);
module.exports = { //incomple webpack config file for succinctness
.
plugins: [
.
defineSnippet,
/*... other plugins */
.
]
.
};
uglify
This function will returns a configuration snippet for to plugin UglifyJS.
decl
declare function uglify(options): {....}
Look here for a full list of options.
default options
The following properties of the options
object are set to the following default if not specified:
cache
: trueinclude
: /.min.js$/extractComments
: truesourceMap
: trueuglifyOptions.compress
: true
Usage:
const wbtk = require('webpack-toolkit');
const { plugin: { uglify } } = wbtk;
module.exports = { //incomple webpack config file for succinctness
.
plugins: [
.
uglify({
sourceMap: false
}),// go with fixed defaults
/*... other plugins */
.
]
.
};
wPackNodeExternals
This function will return a configuration snippet for to plugin webpackNodeExternals. The plugin manages what is included and/or excluded in the final webpack bundle.
decl
declare function wPackNodeExternals(options): { .... }
See hereplugin-externals-options for a all options.
default options
These properties of the options
object are set to the following defaults if not specified:
whitelist
: [] (empty array), the whitelist of modules (will be included into the final bundle)importType
: 'commonjs', Externalize as commonjsmodulesDir
: 'node_modules' (directory of node_modules)modulesFromFile
: false, do not usepackage.json
to get node_module names
Usage:
const wbtk = require('webpack-toolkit');
const { plugin: { wPackNodeExternals } } = wbtk;
module.exports = { //incomple webpack config file for succinctness
.
plugins: [
.
wPackNodeExternals({
whitelist:[ 'debug', 'ms' ] // include the modules "debug" and "ms" in the final bundle
}),
/*... other plugins */
.
]
.
};
hmtl
Examples
TODO