Build a scaffold of webpack4+react+typescript+eslint from scratch

Improving the Packing Configuration of Web Pack

With the basic configuration of webpack, it is not enough to support packages that can be used in production environments. We need to add some configuration.

First of all, it's better to delete the last generated file before each package. Here you can use it. clean-webpack-plugin Plug-in implementation:

$ npm i -D clean-webpack-plugin

Then modify the basic configuration of webpack:

// webpack.base.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  plugins: [
    new CleanWebpackPlugin(),
  ]
}

In the production environment, we want to discard the cache after deploying the new version, and we want to retain the cache of files that have not been changed. In the development environment, we want to completely use the cache, so we need to expand the production and development of two configurations based on the current configuration.

// Packing configuration for webpack.prod.js production environment
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = merge.smart(baseWebpackConfig, {
  mode: 'production',
  devtool: sourceMapsMode,
  output: {
    filename: 'js/[name].[contenthash:8].js', // contenthash: Only if the content of the module changes will the hash value be changed
  },
  plugins: [
    new CleanWebpackPlugin(),
  ]
}
// Configuration of webpack.dev.js development environment
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base');
const config = require('./config');

module.exports = merge.smart(baseWebpackConfig, {
  mode: 'development',
  output: {
    filename: 'js/[name].[hash:8].js',
    publicPath: config.publicPath // Here we can omit it.
  },
  module: {
    rules: [
      {
        oneOf: []
      }
    ]
  },
}

Next, let's edit build.js to make the packager really work:

// config/build.js
const webpack = require('webpack');
const webpackConfig = require('./webpack.prod');

webpack(webpackConfig, function (err, stats) {});

Install tools and add startup commands:

$ npm i -D cross-env
// package.json
{
  "scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --config ./config/webpack.dev.js",
    "build": "cross-env NODE_ENV=production node config/build.js"
  }
}

Then run the packaging command and you can see that the newly generated dist directory contains the packaged files:

$ npm run build

Packaging analysis tools

The packages are typed out, but what is the composition of the packaged documents? Do we pack them correctly according to our needs? We need an analysis tool to help us judge. That's it. webpack-bundle-analyzer.

$ npm i -D webpack-bundle-analyzer

We want to automatically generate or not generate analysis reports when packaging according to the command parameters of packaging.

// webpack.base.js
const argv = require('yargs').argv;
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const merge = require('webpack-merge');

const bundleAnalyzerReport = argv.report; // Decide whether to generate a report based on whether the command parameter contains'report'.
// This configuration will be merged into the final configuration
const webpackConfig = {
  plugins: []
};
if (bundleAnalyzerReport) {
  webpackConfig.plugins.push(new BundleAnalyzerPlugin({
    analyzerMode: 'static',
    openAnalyzer: false,
    reportFilename: path.join(config.assetsRoot, './report.html')
  }));
}
// Merge to merge the configuration
module.exports = merge(webpackConfig, {
  // ...configs
});

Add parameters to the package.json package command:

"scripts": {
  "build": "cross-env NODE_ENV=production node config/build.js --report"
},

Running npm run build will produce a report.html file in the dist directory, which is our analysis report.

Support less and css modules

Now let's make scaffolding support css, less and css modules:

First install tools:

$ npm i -D style-loader css-loader less less-loader

Additional configuration:

// webpack.base.js
module: {
  rules: [
    {
      oneOf: [
        // ... configs
        {
          test: /\.(less|css)$/,
          use: [
            { loader: 'style-loader' },
            {
              loader: 'css-loader',
              options: {
                modules: false // If you want to enable css modules, change to true
              }
            },
            {
              loader: 'less-loader',
              options: { javascriptEnabled: true }
            }
          ]
        },
      ]
    }
  ]
}

Extraction of css

We found that there was no css in the packaged file, but css worked well because webpack did not strip the style out of js.

To facilitate the management of static resources and make full use of caching, we need to package css separately.

First install tools:

$ npm i -D optimize-css-assets-webpack-plugin

Increase packaging configuration:

// webpack.prod.js
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');

// ...webpack configs
optimization: {
  minimizer: [
    new OptimizeCSSAssetsPlugin({
      cssProcessorOptions: true ? { map: { inline: false }} : {}
    })
  ]
}

Running the packaging command, you can see the generated css file.

Automatically add css prefix

Use postcss It can automatically add browser prefix to css.

Installation Dependency:

$ npm i -D postcss-loader autoprefixer

Add web pack configuration:

// webpack.base.js,webpack.prod.js
{
  test: /\.(less|css)$/,
  use: [
    { loader: 'style-loader' },
    {
      loader: 'css-loader',
      options: {
        modules: false
      }
    },
    'postcss-loader', // Pay attention to the insertion location, webpack.prod.js also need to add this item!!!
    {
      loader: 'less-loader',
      options: { javascriptEnabled: true }
    }
  ]
},

New postcss.config.js in the root directory:

module.exports = {
  plugins: {
    autoprefixer: {}
  }
};

Add configuration in package.json:

"browserslist": [
  "> 1%",
  "last 2 versions",
  "not ie <= 8",
  "iOS >= 8",
  "Firefox >= 20",
  "Android > 4.4"
]

Poscss-px-to-viewport example

Here is an example of using postcss to configure the layout based on vh and vw.

Installation Dependency:

$ npm i -D postcss-aspect-ratio-mini postcss-px-to-viewport postcss-write-svg
$ npm i -D cssnano cssnano-preset-advanced

Modify postcss.config.js:

module.exports = {
  plugins: {
    'postcss-aspect-ratio-mini': {}, // Width-to-height ratio of processing element containers
    'postcss-write-svg': { //Processing 1px border
      utf8: false
    },
    'postcss-px-to-viewport': {
      viewportWidth: 750,
      viewportHeight: 1334,
      unitPrecision: 3,
      viewportUnit: 'vw',
      selectorBlackList: ['.ignore', '.hairlines'],
      minPixelValue: 1,
      mediaQuery: false
    },
    cssnano: {
      'cssnano-preset-advanced': {
        zindex: false, // This must be turned off, otherwise all z-index will be set to 1
      }
    },
    autoprefixer: {}
  }
};

After the configuration is completed, if it is based on 750px width design, then 1px on the design can be directly written in the style 1px, packaging will automatically be converted to vw units.

Keywords: Javascript Webpack npm less JSON

Added by friedemann_bach on Mon, 09 Sep 2019 09:27:57 +0300