node package manager
Share your code. npm Orgs help your team discover, share, and reuse code. Create a free org »

webpack-digest

Webpack Digest Crane

Webpack Digest

Commitizen Friendly Semantic Release
Build Status Coverage Report NPM Version License FOSSA Status Canonical Code Style

Webpack Digest is a reusable and extendable Webpack configuration while doing the tedious configuration for you.

The provided Webpack configuration offers sane defaults for common loaders and plugins. Assets include .html, .css, .js, .svg, .png, .jpg, .ico, .gif, .woff(2), .eot, and .ttf. Additional loaders are configured for React (.jsx), Typescript (.ts, .tsx), and Sass (.sass, .scss). Defaults for index.html, favicon, linters (eslint, tslint, stylelint), babel, and express are configured - but can be overridden or extended. Minification, asset extraction, manifest.js and vendor.js extraction, and file hashes, and whole lot more are preconfigured. In development environments, source minification is skipped, source maps are lazily generated, and webpack-dev-middleware and webpack-hot-middleware are configured with the provided express scripts. A Jest config is provided and works with Typescript. A Nightwatch config is also provided.

Warning: this project is still alpha quality with possible breaking changes with each release. Angular2's Hot Loader are in progress.

Install

npm install webpack-digest

It's also suggested cross-env is installed globally to assist with cross-platform environment variable definitions required in the package.json scripts. cross-env is used in the examples below.

npm install -g cross-env

Setup

npm

To use the Webpack Digest config, create a webpack.config.js file in the root of your project and import:

var webpackDigest = require('webpack-digest/lib/webpack.config.js');
 
module.exports = return webpackDigest;

This file is automatically picked up by the webpack command. You can also point webpack directly to Webpack Digest with the --config option.

To run with npm, setup scripts in your project's package.json. The following examples will perform development and production builds, host development or production servers with webpack-digest's provided express scripts, or clean the build and cache directories:

"scripts"{
  "start": "node node_modules/webpack-digest/lib/express/start.js",
  "start:dev": "cross-env NODE_ENV='development' node node_modules/webpack-digest/lib/express/start.js",
  "build": "webpack --progress --colors --display-error-details",
  "build:dev": "cross-env NODE_ENV='development' webpack --progress --colors --display-error-details",
  "clean": "rm -rf public && rm -rf .cache/"
}

Once added to your package.json, run one of the scripts in the terminal:

npm run start:local

Maven

Webpack Digest can also be configured in Maven projects using frontend-maven-plugin. To use with Maven, set the frontend-maven-plugin arguments and environment variables in the pom.xml:

<execution>
  <id>webpack install</id>
  <goals>
    <goal>webpack</goal>
  </goals>
  <configuration>
    <arguments>--config node_modules/webpack-digest/lib/webpack.config.js --display-error-details</arguments>
    <environmentVariables>
      <SRC_PATH>src/main/resources/ui</SRC_PATH>
      <STATIC_PATH>src/main/resources/public</STATIC_PATH>
      <PLATFORMS>react,cssModules</PLATFORMS>
      <NODE_ENV>${NODE_ENV}</NODE_ENV>
    </environmentVariables>
  </configuration>
</execution>

Options

There are many options but Webpack Digest offers sane enough defaults. Most projects should only require a few; often: NODE_ENV and platforms. Options can be loaded from a webpack.digest.config.json file in the root of your project excluding NODE_ENV, DIGEST, and PORT environment variables. For example:

{
  "platforms": {
    "cssModules": true,
    "pragma": "react",
    "typescript": true
  },
  "tsconfig": "demo/tsconfig.json"
}

Environment variables can also be used and take precedent. The examples provided demonstrate with environment variables for clarity, but it is preferred to use them sparingly. webpack.digest.config.json is the preferred method to reduce verbosity in your scripts.

The following table lists the valid options:

webpack.digest.config.js Environment Variable Description Default Options
n/a NODE_ENV Use either production or development. Production features include minification, while development features include linting and HMR. production
n/a DIGEST Path to Webpack Digest settings. It contains these settings. /webpack.digest.config.js
n/a PORT The express host port Default 8080, 8090 when NODE_ENV='development'
cache CACHE Path to store temporary cache files /node_modules/.cache/
config CONFIG Path to Webpack config. See Webpack Config for more details. /webpack.config.js or default config from Webpack Digest
dashboard DASHBOARD Use webpack-dashboard on [on|off]
e2e E2E Path to end-to-end test files for Nightwatch /__e2e__
eslint ESLINT Path to javascript eslint config /.eslintrc or defaults packaged with Webpack Digest
favicon FAVICON Path to favicon.png /SRC_PATH/favicon.png or defaults packaged with **Webpack Digest**
index INDEX Path to index.htm /SRC_PATH/index.htm or defaults packaged with **Webpack Digest**
library LIBRARY Toggle UMD library creation instead. This generates a bundle without dependencies and polyfills false [true|false]
platforms PLATFORMS Comma delimited list of platforms can enable different loader behaviours. cssModules, [react|preact], typescript, angular
polyfills POLYFILLS Path to additional polyfills /polyfills.js or defaults packaged with Webpack Digest
postcss POSTCSS Path to PostCSS config /postcss.config.json or defaults packaged with Webpack Digest
postcssWhitelist POSTCSS_WHITELIST A pipe separated whitelist of packages in node_modules that should be parsed by PostCSS 'reacet-toolbox'
shortName SHORT_NAME An optional shorter name to be used in bundle generation. Useful when generating libraries. The name property in package.json
sourceMaps SOURCE_MAPS Toggle source map generation true [true|false]
srcPath SRC_PATH The project files directory relative to project root. /src
staticPath STATIC_PATH The directory where Webpack will deposit the resulting project relative to project root. /public
stylelint STYLELINT Path to CSS stylelint settings /.stylelintrc or defaults packaged with Webpack Digest
stylelintIgnore STYLELINT_IGNORE Path to CSS stylelint ignore settings /.stylelintignore or defaults comes packaged with Webpack Digest
testConfig TESTCONFIG Path to optional script that is picked up by the provided Jest config to setup additional test suites such as enzyme /testconfig.js
tsconfig TSCONFIG Path to typescript config /tsconfig.json or defaults packaged with Webpack Digest
tslint TSLINT Path to typescript tslint config /tslint.json or defaults packaged with Webpack Digest

Platforms

Typescript

To use Typescript, include the typescript option under platforms:

"scripts"{
  "build": "cross-env PLATFORMS='typescript' webpack --progress --colors --display-error-details"
}

The Webpack Digest configuration processes Typescript files through Webpack just like ordinary Javascript. No additional build step is required and all the same Webpack features work as expected. For typescript IDE integration, extend the provided webpack-digest config by creating a tsconfig.json file in the root of your project:

{
  "extends": "./node_modules/webpack-digest/lib/typescript/tsconfig.json",
}

However, with this default tsconfig.json, typescript files are not able to import Javascript. The setting noImplicitAny is set to true and that prevents javascript files from being imported within typescript files. Set noImplicitAny to false in your tsconfig.json to enable importing javascript:

{
  "extends": "./node_modules/webpack-digest/lib/typescript/tsconfig.json",
  "compilerOptions": {
    "noImplicitAny": false
  }
}

However it is dangerous to turn off noImplicitAny. Only use if you must import javascript. If so, work towards converting all your code to Typescript. It is also possible to import javascript using require(), but this will prevent tree shaking.

At this time, there are several gotcha's with Typescript such as .css, .scss, and .json imports, and using Webpack's System API. These can be resolved in a .d.ts file. Regrettably, it is not possible with the shared tsconfig.json to include a default global.d.ts file while also excluding implicit node_modules definitions. You may create a global.d.ts file in the root of your project or source path and add the following helpful entries:

declare module '*.css';
declare module '*.scss';
 
declare var System: {
  import: any
};
 
declare module "*.json" {
    const value: any;
    export default value;
}
 
declare var BUILD: {
  DATE: string;
}
 
declare var PACKAGE: {
  DESCRIPTION: string,
  NAME: string,
  TITLE: string,
  VERSION: string
}

CSS Modules

When CSS modules are used, a CSS file can be set explicitly global via the .g.css extension. For example, styles.g.css would be loaded globally, while styles.css would load as a CSS module. CSS files from node_modules are always global.

When using React, React CSS modules Babel plugin is included and the styleName property will become available in your components

Extending

Webpack Config

It's easy to extend the Webpack Digest Webpack configuration. Simply edit the webpack.config.js in the root of your project and modify the imported the webpack-digest webpackDigest object to your liking. Projects such as webpack-merge and webpack-config can help extend the webpack-digest config object.

/* Example webpack.config.js */
var webpackDigest = require('webpack-digest/lib/webpack.config.js');
 
function extend(config) {
  /* Modify the config */
  return config;
}
 
module.exports = extend(webpackDigest);

If you use a different file name or path for your webpack.config.js, you can refer to your extended config explicitly in your build scripts with webpack's --config option:

"scripts"{
  ...
  "build": "cross-env webpack --config webpack.config.js --progress --colors --display-error-details"
}

Express

It's also easy to extend the default express app configuration. Simply create a server.extend.js file and import webpack-digest's app.js. After extending, serve express or use the provided server.js:

Note that to avoid complications with non-root routes, the root / route and HTML5 /* catch-all are not implemented in the default app.js and will have to be provided. See example below.

 
/* Example server.extend.js */
var app = require('webpack-digest/lib/express/app.js');
var proxy = require('http-proxy-middleware');
 
// *** Root route ***
app.use(
  '/',
  express.static(path.join('public'))
);
 
// *** For HTML5 Routing ***
app.all(
  '/*',
  (request, response) => {
    response.sendFile(path.join('public', 'index.html'));
  }
);
 
app.get('/env', function(req, res){
  res.json({
    env: 'qa'
  })
})
 
app.use('/api', proxy({
  target: 'http://localhost:9090',
  changeOrigin: true
}))
 
/* Optionally, serve with provided server.js */
var server = require('webpack-digest/lib/express/server.js');
 
server(app);

Then remember to reference your server.extend.js in the projects package.json scripts:

"scripts"{
  "start": "cross-env PLATFORMS='react,cssModules' node server.extend.js"
  ...
}

If you are using or extending the provided app and express server, then follow same as above; a Webpack config called webpack.config.js located in the project root will be resolved automatically. If your extended config has a different name or path, the default express will require the path given via the CONFIG environment variable:

"scripts"{
  "start": "cross-env CONFIG='configs/webpack.js' node node_modules/webpack-digest/lib/express/start.js"
  ...
}

This also includes definitions for webpack-digest globals such as BUILD and PACKAGE. The provided example is tracked here.

Jest

Jest can be tricky to setup in this kind of configuration because Webpack and Babel configurations are not in the root directory. A Jest configuration is provided but it is not extendible. However, it can be copied to your root directory and modified further if needed. The provided Jest config does work with Typescript.To use the provided Jest configuration, simply include the following scripts in your package.json*:

scripts: {
  ...
  "test": "cross-env node_modules/.bin/cross-env PLATFORMS='react,cssModules' jest --config node_modules/webpack-digest/lib/jest/config.js --no-cache --coverage",
  "test:dev": "cross-env node_modules/.bin/cross-env PLATFORMS='react,cssModules' jest --config node_modules/webpack-digest/lib/jest/config.js --no-cache --watch"
}

* Note : Remember to include all relevant environment variabels from your production and development scripts in your test scripts.

The TESTCONFIG option is for additional test suite configuration when using the provided Jest config. By default it will look for a testconfig.js file in the root of the project. This file is run via Jests setupFiles option. This is required when using some libraries like enzyme. For example:

import {configure} from 'enzyme';
import Adapter from 'enzyme-adapter-react-15';
 
configure({adapter: new Adapter()});

Nightwatch

Nighwatch is also not extendable, but if you must you may copy the provided configuration and build from there. The following are examples using the provided default nightwatch config:

scripts: {
  "selenium": "node node_modules/webpack-digest/lib/nightwatch/conf.js",
  "nightwatch": "sleep 1 && nightwatch --config node_modules/webpack-digest/lib/nightwatch/conf.js --env phantomjs"
}

The "selenium" script must be run at least once in order to download the latest selenium binaries. (Note: selenium requires a Java path be installed in the local environment) The binaries are installed within node_modules, so any time that directory is removed, this script must be run again.

The "nightwatch" script may be run after the selenium binary has been downloaded. Nightwatch will look for test files within the __e2e__ directory at the root of the project, unless overridden by the E2E property.

ESLINT / TSLINT / STYLELINT

eslint, tslint, and stylelint run during every webpack build. However, it is also common for IDE's to have built in linters which load the respective lint config file. These three linters offer extends options, which allow a config file to extend another. Using extends, you can include the following lint files to extend the configs provided by Webpack Digest to the root of your project. Additionally, this is how you would add new rules or override the defaults.

.eslintrc

{
  "extends": "./src/lint/.eslintrc"
}

tslint.json

{
  "extends": "./src/lint/tslint.json"
}

.stylelintrc

{
  "extends": "./src/lint/.stylelintrc"
}

Note: you do not have to extend the Webpack Digest rules. During a build, when these files are present in the root of your project, they will be used instead of the defaults. Meaning if your project includes one of these configs and omits the extends, you are starting with a blank slate.

License

GPLv3