How to configure WebPack from 0

Anyone who has configured WebPack should know that WebPack is really complicated. At the beginning of the project, I took others’ ready-made to make small modifications, but after all, others’ did not have their own comfort. So I decided to write this article to take you through the WebPack configuration from my configuration and simplify the complexity of reading the webPack official page.

First we need to be clear about what we’re asking WebPack to do.

1. What you write is what you get. We write code in the compiler and it immediately appears on the debugger (hot update service).

2. Cross-domain problems in obtaining data from local development (agent, solve cross-domain)

3. Use ES678,less,sass, etc. (translation, let the browser understand our code)

4. Improve project performance, such as code compression, image compression, etc. (project optimization)

If there is a requirement related to the input, look for entry (for example, multiple pages with multiple entries) 6. If there is a requirement related to output, look for output (e.g. you need to define the path to the output file, name, etc.) 7. For requirements related to module addressing, look for resolve (such as defining the alias) 8. If there are requirements related to translation, look for a Loader (such as sASS processing es678N) 9. If there are requirements related to the build process, look for plugins (for example, I need to copy the packaged files to a directory and commit them to Git once they are packaged). Let’s take a look at some basic webPack configurations

1. Project entry

2. Output (export file)

3. Modules

4. The plugin (plug-in)

5.resolve

6.devserver

7.mode,

8devtool

1. Entry Settings

There are three main ways

1. The value is a string

Entry:'.src/main.js'
Copy the code

2. The format is an array

entry: [react, react-dom]
Copy the code

3. Object form

entry: {
    main:'./src/index2.js',
    second: './src/index2.js',
    vendor:['react'.'react-dom']}Copy the code

2. Export file Settings and (Output)

const path = require('path');
module.exports = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js'}};Copy the code

In the example above, we use the output.filename and output.path attributes to tell the Webpack bundle name and where we want the bundle generation (emit) to go. What is path. resolve and what does the imported Path module do

Nodejs

The path.resolve() method resolves a series of paths or path segments into absolute paths.

A given sequence of paths is processed from right to left, and then each path path is preloaded until the absolute path is constructed. For example, given a sequence of path segments: /foo, /bar, baz, calling path.resolve(‘/foo’, ‘/bar’, ‘baz’) will return /bar/baz.

If an absolute path has not been generated after all given segments of PATH have been processed, the current working directory is used. The generated path is normalized, and the trailing slash is removed unless the path is resolved to the root directory. The zero-length path segment is ignored.

If there is no path segment, path.resolve() returns the absolute path to the current working directory.

path.resolve('/foo/bar'.'./baz');
// Returns: '/foo/bar/baz'
path.resolve('/foo/bar'.'/tmp/file/');
// Returns: '/tmp/file'
path.resolve('wwwroot'.'static_files/png/'.'.. /gif/image.gif');
// If the current working directory is /home/myself/node,
// this returns '/home/myself/node/wwwroot/static_files/gif/image.gif'
_dirname
Copy the code

The directory name of the current module. This is the same as path.dirname() ‘s __filename.

Example: node example.js runs /Users/ MJR from it

console.log(__dirname);
// Prints: /Users/mjr
console.log(path.dirname(__filename));
// Prints: /Users/mjr
Copy the code

Output is one of the most common ones we use when configuring output

Filename This is the name of the output file. If there is only one output file, it can be written as a static name. For example,

output:{
     filename:'bundle.js'
}
Copy the code

Of course, in our daily work, usually this is not the case, when the project is very large, if you do not block, bundle.js will be surprisingly large, the bigger the project, the bigger the bundle.js will be, this is not the focus of today’s discussion, later

What happens when there are multiple chunks

Webpack gives each generated Chunk a name. The Chunk name is related to the configuration of the Entry:

1. If the entry is a string or array, only one chunk is generated. The chunk name is main.

2. If the entry is an object, multiple chunks may occur. In this case, the chunk name is the name of the key in the object key-value pair

However, when multiple entries are created through multiple entry points, code splitting, or various plugins

Bundles, you should use one of the following alternatives to give each bundle a unique name… Use entry name:

output:{
     filename: "[name].bundle.js"
}
Copy the code

Use the internal chunk ID

output:{
    filename: "[id].bundle.js"
}
Copy the code

Use a unique hash generation during each build

output:{
filename: "[name].[hash].bundle.js"
}
Copy the code

Using a hash based on the content of each chunk:

output:{
filename: "[chunkhash].bundle.js"
}
Copy the code

Here are some unfamiliar words, hash, chunkhash, what are they? Difference between hash, Chunkhash, and Contenthash Hash

The hash values are the same if they are all used because this is at the engineering level, that is, every time you modify any file, the hash values of all filenames will change. So if any of the files are modified, the entire project’s file cache will be invalidated. So for a module that has not changed, this is obviously not appropriate because the cache is invalid. This is where chunkhash comes in. chunkhash

Only the file name and hash value of the modified file are modified

filename: ‘[name]-[chunkhash].js’

When we use the mini-css-extract-plugin to split CSS, we need to use chunkhash, which is the CSS file I introduced in a JS file. If I have changed js but not CSS, I can cache the CSS file through Chunkhash

contenthash

After chunkhash is used for CSS, we test and find that if we change js, the hash value of the CSS file name does not change, but if we change the CSS file, we will find that the chunkhash value of the CSS file name does not change, thus invalidating our non-overwrite CSS file. The important thing to note here is that CSS files must use Contenthash.

Id, name, hash, chunkhash, etc. are all built-in webpack variables. Id is unique and will not be used twice. Start from 0 and name is the module name. chunkFilename

This option determines the name of the non-entry chunk file. Which scenario is required?

When a module is loaded on demand (asynchronously), i.e., the route is lazy loaded, and the file is not listed in the entry.

Such as

{
    entry: {
        "index": "pages/index.jsx"
    },
    output: {
         filename: "[name].min.js",
        chunkFilename: "[name].min.js"
    }
}
const myModel = r => require.ensure([], () => r(require('./myVue.vue')), 'myModel')
Copy the code

In the example above, the output is index.min.js, so the generated filename is chunkname. The output of chunkFilename is myModel.min.js, so chunkFilename is also important!! Path Indicates the local directory where the configuration output file is stored. The value is a string of characters and is an absolute path

output:{
    path: path.resolve(__dirname, 'dist/assets')}Copy the code

PublicPath asynchronously loads the built resources (images, files), The value of this option is prefixed by each URL created by Either Runtime or Loader. Therefore, in most cases, the value of this option will end with /. The default value is an empty string “”, which is the relative path, and an incorrect configuration will result in 404. Simply put, static files are hosted on the CDN.

output:{
    filename:'[name]_[chunkhash:8].js',
    publicPath:'https://www.qdtalk.com/assets/'
}
Copy the code

This is what an HTML page looks like when packaged and compiled

Both Path and publicPath support string templates

  • Configure single egress // Webpack configuration
const path = require('path');

module.exports = {
  entry: main: './src/main.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist')}};Copy the code
  • Configuring multiple Egress
// webPack configures const path = require('path');

module.exports = {
  entry: {
    app: './src/app.js',
    vendors: './src/vendors.js'
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'dist')}};Copy the code

3. Modules

The module handles the configuration of the loader

This section refers to the definition of loader on the official website

Loader allows WebPack to process files that are not JavaScript (WebPack itself only understands JavaScript). Loader converts all types of files into valid modules that WebPack can handle, and then you can take advantage of WebPack’s packaging capabilities to process them.

Essentially, the WebPack Loader converts all types of files into modules that the application’s dependency graph (and eventual bundle) can refer to directly. Note that the Loader can import any type of module (such as.css files), which is a webPack-specific feature that may not be supported by other packagers or task executors. We believe this language extension is necessary because it allows developers to create more accurate dependency diagrams. At a higher level, the Loader has two goals in the Configuration of WebPack:

1. The test attribute identifies the file or files that should be converted by the corresponding Loader.

2. The use attribute, which loader should be used for the conversion.

webpack.config.js
const path = require('path');
const config = {
  output: {
    filename: 'my-first-webpack.bundle.js'
  },
  module: {
    rules: [
      { test: /\.txt$/, use: 'raw-loader'}}}; module.exports = config;Copy the code

In the previous configuration, we defined the rules property for a single Module object, which contains two required properties: test and use. This tells the WebPack compiler the following:

“Hey webpack compiler, when you come across ‘paths that are parsed to ‘.txt’ in require()/import statements’, use raw-Loader to convert it before you package it.” It is important to remember that when loader is defined in the WebPack configuration, it is defined in module.rules, not rules. However, WebPack gives serious warnings when defining errors. In order for you to benefit from this, WebPack will “give a serious warning” if you don’t do it the right way

There are many loaders in WebPack, here I follow the official document to explain and I understand the use of loader features

  • Almost all loaders need to be installed, but do not need to be introduced through require in the Webpack configuration file
  • Reverse compile, chain pass files
  • Raw-loader Loads the original content of the file (UTF-8)
  • The val-Loader executes the code as a module and converts exports to JS code
  • Url-loader works like a File Loader, but can return a data URL if the file is smaller than the limit
  • File-loader sends the file to the output folder and returns the (relative) URL raw-Loader allows you to import the file in your code
import txt from './file.txt';
Copy the code

Modules loaded by the Val-Loader must use the following function interface to export default export as a function.

function answer () {
  return {
    code: 'module.exports = 42; '}}; module.exports = answer;Copy the code

url-loader

Url-loader functions like file-Loader, but returns a DataURL if the file size (in bytes) falls below the specified limit. File-loader sends the file to the output folder and returns the (relative) URL (no further processing of the file) JSON

  • Json-loader loads json files (included by default)
  • Json5 – Loader loads and translates JSON 5 files
  • Son-loader loads and interprets CSON files and mainly processes JSON files

Conversion compilation (Transpiling)

  • Script-loader executes JavaScript files once in the global context (such as in script tags) without parsing
  • Babel-loader loads the ES2015+ code and uses Babel to translate it into ES5
  • Buble-loader loads the ES2015+ code using Buble and translates the code to ES5
  • Traceur-loader loads the ES2015+ code, which is then translated to ES5 using traceur
  • Ts-loader or awesome- typescript-Loader loads typescript 2.0+ just like JavaScript
  • Coffee-loader loads CoffeeScript like JavaScript

During React development we needed to translate JSX or ES6 code into ES5 code. We need to use babel-Loader

{
'test': / \. (js | JSX) $/, / / the Babel is converted to compatibility of js'exclude': /node_modules/,
'loader': 'babel-loader'.'query': {
'presets': ['react'.'latest'.'stage-0'.'react-hmre']},'include': path.resolve(__dirname, '.. /client')},Copy the code

Query === options Babel version 6 and Babel version 7 have different Settings. Templating will fail if references are wrong

  • Html-loader exports HTML as a string and needs to reference static resources
  • Pug-loader loads the pug template and returns a function
  • Jade – Loader loads the Jade template and returns a function
  • Markdown – Loader translates markDown into HTML
  • The React-Markdown-loader uses the Markdown-parse parser to compile markDown into the React component
  • Posthtml – Loader loads and converts HTML files using posthTML
  • Handlebars – Loader transfers handlebars to HTML
  • The markup-inline-Loader converts inline SVG/MathML files to HTML. Useful when applying icon fonts, or CSS animations to SVG.

style

  • Style-loader adds the module’s export to the DOM as a style
  • Css-loader parses the CSS file, uses import to load it, and returns the CSS code
  • Less-loader loads and translates less files
  • Sass-loader loads and translates sass /SCSS files
  • Postcss-loader loads and translates CSS/SSS files using postCSS
  • The stylus loader loads and translates the stylus file. If we are using less or sass in our development, we need to convert it to CSS before importing it into the project
{
'test': /\.less$/,
'loader': ['style-loader'.'css-loader', {
'loader': 'less-loader'.'options': {
'javascriptEnabled': true}}},Copy the code

The order of execution here. Less-loader -> csS-loader -> style-loader -> Linting

  • Mocha – Loader uses Mocha tests (browser /NodeJS)
  • Eslint-loader PreLoader, which uses ESLint to clean up code
  • Jshint -loader PreLoader, using jshint to clean up the code
  • Jscs-loader PreLoader that uses JSCS to check code styles
  • Coverjs-loader PreLoader that uses CoverJS to determine test coverage

Framework (Frameworks)

  • Vue-loader loads and translates the VUE component
  • Polymer-loaders are processed using a selective preprocessor and require() Web components that are like first-class modules
  • Angular2-template-loader loads and translates Angular components

Key points (knock on the blackboard)

The plugins (plug-in)

Function: Can handle a variety of tasks, from packaging, optimization and compression, to redefining variables in the environment without requiring the require. plugin

Loaders are used to convert certain types of modules, while plug-ins can be used to perform a wider range of tasks. Plug-ins can range from packaging optimizations and compression to redefining variables in the environment. The plug-in interface is extremely powerful and can be used to handle a wide variety of tasks.

To use a plug-in, all you need to do is require() it and then add it to the plugins array. Most plug-ins can be customized by option. You can also use the same plug-in multiple times in a configuration file for different purposes, and you need to create an instance of it by using the new operator. Below is an example of the plugins I configured for the development environment

webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin'); // install const webpack via NPM = require('webpack'); Const config = {module: {rules: [{test: /\.txt$/, use: 'raw-loader' }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({template: './src/index.html'}})]; module.exports = config;Copy the code
'plugins': [new webpack. Optimize. OccurrenceOrderPlugin (), / / adjustment module pack order, New Webpack.defineplugin ({// DefinePlugin allows you to create a global constant that can be configured at compile time.'process.env.NODE_ENV': JSON.stringify('development')}), new HtmlWebpackPlugin({// HtmlWebpackPlugin simplifies the creation of HTML files to serve your WebPack. This is especially useful for Webpack bundles that include a hash in the file name that changes each time it is compiled. You can have the plugin generate an HTML file for you, provide your own template using the Lodash template, or use your own loader.'hash': true.'title': 'Demo'.'filename': 'index.html'.'template': path.resolve(__dirname, '.. /views/index.ejs'),
'inject': 'body'}), new webpack. HotModuleReplacementPlugin (), / / to enable hot update new webpack. NoEmitOnErrorsPlugin (), / / output stage encounter compiler error. Skip new webpack NamedModulesPlugin (), / / when open HMR using the relative path of the plugin will display module, Suggestions for the development environment. New webpack.progressplugin (), // output build progress]Copy the code