Build your own web pack development environment from 0

Posted by activeradio on Tue, 17 Sep 2019 17:04:42 +0200

Last review: Build your own web pack development environment from 0 (1)

loaderIt is mainly used to convert the original content of the module into new content according to the requirement, so that it can be used to load non-components. JS Modular!
By using differentloaderWebpackYou can convert different files into JS Documents, such as CSS,ES6/7,JSX And so on.

Let's take a look at what we have to master. loader!

1.loader Compiling

1.1 loader Use

  • test: Regular expressions matching extensions of processed files
  • use: loader Name is the name of the module you want to use.
  • include/exclude: Manually specify folders that must be processed or mask folders that do not need to be processed
  • options: by loaders Provide additional settings

defaultloaderThe order of execution isFrom bottom to top,*From right to left, of course, the execution order can also be defined manually. Next, let's introduce the common ones in turn.loader,To feelloaderCharm!

We continue to write based on this basic configuration.:

const path = require("path");
const dev = require("./webpack.dev");
const prod = require("./webpack.prod");
const merge = require("webpack-merge");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const base = {
  entry:'./src/index.js',
  output: {
    filename: "[name].js",
    path: path.resolve(__dirname, "../dist")
  },
  plugins: [
    new HtmlWebpackPlugin({
        filename: 'index.html',
        template: path.resolve(__dirname, "../public/template.html"),
        hash: true,
        minify: {
            removeAttributeQuotes: true
        }
    }),
    new CleanWebpackPlugin({
        cleanOnceBeforeBuildPatterns: [path.resolve('xxxx/*'),'**/*'],
    }),
  ]
};
module.exports = env => {
  if (env.development) {
    return merge(base, dev);
  } else {
    return merge(base, prod);
  }
};

2. Processing CSS files

2.1 parsing css Style

We introduce css style in js file!

import './index.css';

When the package is executed again, css is prompted that it cannot be parsed

ERROR in ./src/index.css 1:4
Module parse failed: Unexpected token (1:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders

At this point you need to install loader

npm install style-loader css-loader --save-dev
module: {
  rules: [
    {
       test: /\.css$/,
       use: ["style-loader", "css-loader"]
    }
  ]
}

2.2 Extract Style Files

Style extraction by default only when packaged

module.exports = env => {
  let isDev = env.development;
  const base = {/*source...*/}
  if (isDev) {
    return merge(base, dev);
  } else {
    return merge(base, prod);
  }
};

Install pull-out plug-in

npm install mini-css-extract-plugin --save-dev

Configuration pull-out plug-in

{
    test: /\.css$/,
    use: [
        !isDev && MiniCssExtractPlugin.loader,
        isDev && 'style-loader',
        "css-loader"
    ].filter(Boolean)
}
!isDev && new MiniCssExtractPlugin({
    filename: "css/[name].css"
})

The final file configuration is pasted:

const path = require("path");
const dev = require("./webpack.dev");
const prod = require("./webpack.prod");
const merge = require("webpack-merge");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = env => {
  let isDev = env.development;
  const base = {
    entry: "./src/index.js",
    output: {
      filename: "[name].js",
      path: path.resolve(__dirname, "../dist")
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            !isDev && MiniCssExtractPlugin.loader,
            isDev && 'style-loader',
            "css-loader"
          ].filter(Boolean)
        }
      ]
    },
    plugins:[
        !isDev && new MiniCssExtractPlugin({
          filename: "css/[name].css"
        }),
        new HtmlWebpackPlugin({
          filename: "index.html",
          template: path.resolve(__dirname, "../public/template.html"),
          hash: true,
          minify: {
            removeAttributeQuotes: true
          }
        }),
      ].filter(Boolean)
  };
  if (isDev) {
    return merge(base, dev);
  } else {
    return merge(base, prod);
  }
};

2.3 css preprocessor

Different css preprocessors need different loader s for parsing

  • sass: sass-loader node-sass
  • less: less-loader less
  • stylus: stylus-loader stylus

Using sass

{
    test:/\.scss$/,
    use:[
        !isDev && MiniCssExtractPlugin.loader,
        isDev && 'style-loader',
        "css-loader",
        "sass-loader"
    ].filter(Boolean)
}

The @import grammar may be used to refer to css files in css files, and scss may also be imported into the referenced css files.

{
    test: /\.css$/,
    use: [
    !isDev && MiniCssExtractPlugin.loader,
    isDev && 'style-loader',
    {
        loader:"css-loader",
        options:{
            importLoaders:1 // The imported file needs to be processed by calling sass-loader 
        }
    },
    "sass-loader"
    ].filter(Boolean)
},

2.4 Processing Style Prefixes

Use postcss-loader to add style prefix

npm install postcss-loader autoprefixer

Add prefix before processing css

 {
    test: /\.css$/,
    use: [
    !isDev && MiniCssExtractPlugin.loader,
    isDev && 'style-loader',
    {
        loader:"postcss-loader",
        options:{
            plugins:[require('autoprefixer')]
        }
    },
    "postcss-loader",
    "sass-loader"
    ].filter(Boolean)
},

Or you can create the postcss configuration file postcss.config.js

module.exports = {
    plugins:[
        require('autoprefixer')
    ]
}

Browser compatibility range can be configured .browserslistrc

cover 99.5%

2.5 css compression

In a production environment, we need to compress css files, configure minimizer options, and install compression plug-ins.

npm i optimize-css-assets-webpack-plugin terser-webpack-plugin --save-dev

Configure compression in webpack.prod.js file

const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
optimization:{
    minimizer:[new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})]
}

2.6 File Fingerprint

  • Hash: Hash value for the entire project
  • chunkhash: generates hash values based on entries
  • contentHash: hash value generated based on the content of each file

We can use hash stamp reasonably to cache files.

!isDev && new MiniCssExtractPlugin({
    filename: "css/[name].[contentHash].css"
})

3. Processing file types

3.1 Processing referenced pictures

import logo from './webpack.png';
let img = document.createElement('img');
img.src = logo;
document.body.appendChild(img);

Using file-loader, the image is packaged and the packaged path is returned.

{
    test:/\.jpe?g|png|gif/,
    use:{
        loader:'file-loader',
        options:{
            name:`img/[name].[ext]`
        }
    }
}

3.2 Processing icon

Binary files are also packaged using file-loader

{
    test:/woff|ttf|eot|svg|otf/,
    use:{
        loader:'file-loader'
    }
}

3.3 converted to base64

Using url-loader to convert the qualified picture into base64, the url-loader that does not satisfy the condition will automatically call file-loader for processing.

{
    test:/\.jpe?g|png|gif/,
    use:{
        loader:'url-loader',
        options:{
            limit:100*1024,
            name:`img/[name].[ext]`
        }
    }
}

4. summary

Through the use of loader, we know that loader can process other types of modules into JS modules for loading and using. This is actually part of a very important confusion dependency in webpack.
In the next article, we will discuss how to parse and process JS module. I hope you will continue to pay attention to and support it.

Topics: Javascript Webpack sass npm less