1.0.15 • Published 6 years ago

webpack-toolbox v1.0.15

Weekly downloads
2
License
GPL-3.0
Repository
github
Last release
6 years ago

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,
        },
    }];
}

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): {..};

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): {..};

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): {..};

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): {..};

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 the file function.
  • ruleOptions configure the specific webpack rule

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): {..};

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
   }

This rule will always have these unchangable properties fixed:

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 the tslint function.
    • property typecheck is always set to false.
  • ruleOptions configure the specific webpack rule
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 to styles.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 the clean-webpack-plugin.
    1. property options.paths: array of 1 or more paths that needs to be deleted
    2. property options.root: defaults to <projectdir>/dist if root is not specified in options.
    3. property options.* (* is wildcard property other then paths in "1.") are passed to the clean-webpack-plugin

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: true
  • include: /.min.js$/
  • extractComments: true
  • sourceMap: true
  • uglifyOptions.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 commonjs
  • modulesDir: 'node_modules' (directory of node_modules)
  • modulesFromFile: false, do not use package.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