How do I automatically add bundles generated at build time to HTML

Using the HtmlWebpackPlugin, a new index.html file will be generated to replace our original file.

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
 
 module.exports = {
   entry: {
     index: './src/index.js',
     print: './src/print.js',
   },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'Output Management',
    }),
  ],
   output: {
     filename: '[name].bundle.js',
     path: path.resolve(__dirname, 'dist'),
   },
 };
Copy the code

How to clean up (webPack-generated files are placed in)/distfolder

Webpack generates files and places them in the /dist folder, but it doesn’t keep track of which files are actually used in the project.

Use the clean-webpack-plugin to clean up the /dist folder before each build so that only the files used are generated.

How do I map compiled code back to the original source

When Webpack packages source code, it can be difficult to trace the original locations of Errors and warnings in the source code.

To make it easier to track errors and warnings, JavaScript provides source maps that map compiled code back to the original source code.

const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); Module.exports = {// Note: Source map is resource-intensive for development environments only. // Avoid inline-*** and eval-*** in production because they increase bundle size and reduce overall performance: 'development', entry: { index: './src/index.js', print: './src/print.js', }, devtool: 'inline-source-map', plugins: [ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ title: 'Development', }), ], output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist'), }, };Copy the code

How do I automatically compile code after it changes

Webpack provides the following methods:

  • webpack --watchCommand line (Watch modewatch mode)

Disadvantages: You need to manually refresh the browser to see the actual effect of the modification

  • webpack serve --openThe command line,webpack-dev-server)

Webpack-dev-server provides a simple Web server with live reloading

Note: Webpack-dev-server is not written to any output files after compilation. Instead, you keep the bundle files in memory and then serve them to the server as if they were real files mounted on the server root path. If your page wants to find the bundle files in a different path, you can change this using the publicPath option in the Dev Server configuration.

const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { mode: 'development', entry: { index: './src/index.js', print: './src/print.js', }, devtool: 'inline-source-map', devServer: {contentBase: './dist',// from where to find file serve}, [ new CleanWebpackPlugin({ cleanStaleWebpackAssets: false }), new HtmlWebpackPlugin({ title: 'Development', }), ], output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist'), }, };Copy the code
  • usewebpack-dev-middleware

Webpack-dev-middleware is a wrapper that sends webPack-processed files to a server.

Webpack-dev-server uses it internally, but it can also be used as a separate package for more customization as needed.

Can be used in combination with ExpressJS (custom setup server), etc

You’ll need to manually refresh your browser to see the changes in action, and use the Webpack-hot-Middleware dependency package to enable HMR on your custom server or application

server.js

const express = require('express'); const webpack = require('webpack'); const webpackDevMiddleware = require('webpack-dev-middleware'); const app = express(); const config = require('./webpack.config.js'); const compiler = webpack(config); // Tell Express to use webpack-dev-middleware, // and use the webpack.config.js configuration file as the base configuration. app.use( webpackDevMiddleware(compiler, { publicPath: config.output.publicPath, }) ); // Serve the file to port 3000. app.listen(3000, function () { console.log('Example app listening on port 3000! \n'); });Copy the code

Method of code separation

  1. Entrance to the starting point

    Disadvantages:

  • Multiple Manual configurations
  • If the entry chunks contain duplicate modules, those duplicate modules are introduced into each bundle.
  • This approach is not flexible and does not dynamically separate the code from the core application logic
  1. To prevent the repeat
  • Entrance to rely on

Configure the dependOnoption option so that modules can be shared between chunks

const path = require('path'); module.exports = { mode: 'development', entry: { index: { import: './src/index.js', dependOn: 'shared', }, another: { import: './src/another-module.js', dependOn: 'shared', }, shared: 'lodash', }, output: { filename: '[name]. Bundle. Js, path: the path. The resolve (__dirname,' dist),}, / / note: to be used on an HTML page is required for a multiple entry set optimization. RuntimeChunk: 'single' to split runtime code into a single chunk optimization: {runtimeChunk: 'single',},};Copy the code
  • SplitChunksPlugin

The SplitChunksPlugin plug-in can extract a common dependency module into an existing chunk of entry or into a newly generated chunk.

const path = require('path');

  module.exports = {
    mode: 'development',
    entry: {
      index: './src/index.js',
      print: './src/print.js',
    },
    output: {
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, 'dist'),
    },
    
   optimization: {
     splitChunks: {
       chunks: 'all',
     },
   },
  };
Copy the code
  1. Dynamic import
  • ECMAScript proposalimport()grammar(recommended)
  • Webpack specificrequire.ensure

Pay attention to

Import () calls will use promises internally. If you use import() in older browsers (IE 11, for example), remember to use a polyfill library (es6-Promise or promise-polyfill, for example) to implement promises.

Since import() returns a promise, it can be used with async functions.

Prefetch/preload

  • Prefetch: Resources that may be required for some future navigation
/ /... import(/* webpackPrefetch: true */ './path/to/LoginModal.js');Copy the code

This generates and appends to the header of the page, indicating that the browser prefetches the login-modal-chunk.js file during idle time.

  • Preload: Resources may be required under the current navigation

ChartComponent.js

/ /... import(/* webpackPreload: true */ 'ChartingLibrary');Copy the code

When using ChartComponent in a page, chartComponent.js is requested along with charting-library-chunk. Assuming that page-chunk is large and slow to load, the page will display a LoadingIndicator until the Charting-library-chunk request completes and the LoadingIndicator disappears. Starting requires very little load time because there is only one round trip, not two. Especially in high latency environments.

Note: Improper use of webpackPreload can hurt performance

The preload directive differs from the prefetch directive in a number of ways:

  • preloadChunk starts loading in parallel when the parent chunk loads.prefetchChunk starts loading after the parent chunk finishes loading.
  • preloadChunk has a medium priority and is downloaded immediately.prefetchChunk downloads while the browser is idle.
  • preloadThe chunk will be requested immediately in the parent chunk for the present moment.prefetchChunk will be used at some point in the future.
  • Browser support varies.

Analysis of the bundle

  • analyseOfficial: You can run this command linewebpack --profile --json > stats.jsonGenerate the required JSON files
  • webpack-chart: WebPack Stats interactive pie chart.
  • webpack-visualizerVisualize and analyze your bundles to see which modules take up space and which are likely to be reused.
  • webpack-bundle-analyzer: a plugin and CLI tool that presents bundle content as a convenient, interactive, scalable tree.
  • webpack bundle optimize helper: This tool analyzes your bundles and provides actionable improvements to reduce their size.
  • bundle-stats: Generates a bundle report (bundle size, resources, modules) and compares the results between different builds.

The cache

Ensure that files generated by webPack compilation can be cached by the client and that new files can be requested if the file contents change.

const path = require('path'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/index.js', plugins: [// For v2 versions of the CleanWebpackPlugin, Use new CleanWebpackPlugin(['dist/*']) new CleanWebpackPlugin(), new HtmlWebpackPlugin({title: 'Caching', }), ], output: { filename: '[name].[contenthash].js', path: Resolve (__dirname, 'dist'),}, optimization: {// Resolve vendor bundle changes with its module.id. 'Deterministic ', runtimeChunk: 'single',// Extract the boot template and split the Runtime code into a single chunk splitChunks: CacheGroups: {vendor: {test: {cacheGroups: {vendor: {test: /[\\/]node_modules[\\/]/, name: 'vendors', chunks: 'all', }, }, }, }, };Copy the code

Building performance improvements

  • By using the include field, loader applies only to the module that actually needs to convert it

  • Improve parsing speed

    • To reduceresolve.modules.resolve.extensions.resolve.mainFiles.resolve.descriptionFilesBecause they increase the number of file system calls.
    • If you don’t usesymlinks(e.g.npm linkoryarn link), can be setresolve.symlinks: false.
    • If you use customresolve pluginRule, and not specifiedcontextContext, which can be setresolve.cacheWithContext: false
  • Use the DllPlugin to generate separate compilation results for code that changes infrequently

  • Try to keep chunks small

    • Use less quantity/volumelibrary.
    • Used in multi-page applicationsSplitChunksPlugin.
    • Used in multi-page applicationsSplitChunksPluginAnd openasyncMode.
    • Remove unreferenced code.
    • Only compile the code you are currently developing.
  • Don’t use too many workers

Thread – loaders can be distributed to a worker pool(worker pool).

Note: Don’t use too many workers because node.js runtime and Loader have startup overhead. Minimize module transfers between worker and main process. Inter-process communication (IPC) is very resource-intensive.

  • Persistent cache

  • Removing the ProgressPlugin from the Webpack reduces build time.

  • Minimize the number of preset/ plugins in the project.

  • Use fork-ts-checker-webpack-plugin for type checking in a separate process.

  • Configure the Loader to skip type checking.

  • When ts-Loader is used, happyPackMode: true/transpileOnly: true.

  • There is a bug in Node-sass that blocks threads from the Node.js thread pool. When thread-Loader is used, you need to set workerParallelJobs: 2

How do you configure your development and build environments independently and merge common parts

In a development environment, we need: a powerful source map and a Localhost Server with live reloading or hot Module replacement capabilities.

In production, the goal is to focus on bundle compression, lighter source maps, resource optimizations, and so on to improve load times.

Use the Webpack-merge tool, which references the “common” configuration to avoid repeating code in environment-specific configurations

Resource module

Asset Module is a module type that allows you to use resource files (fonts, ICONS, etc.) without having to configure an additional loader.

Before WebPack 5, it was common to use:

  • raw-loaderImport the file as a string
  • url-loaderInline the file as a data URI into the bundle
  • file-loaderSend the file to the output directory

Asset Module Type replaces all of these loaders by adding 4 new module types:

  • asset/resourceSend a separate file and export the URL. Previously by usingfile-loaderThe implementation.
  • asset/inlineExport the data URI of a resource. Previously by usingurl-loaderThe implementation.
  • asset/sourceExport the source code of the resource. Previously by usingraw-loaderThe implementation.
  • assetAutomatically choose between exporting a data URI and sending a separate file. Previously by usingurl-loaderAnd configure the resource volume limitation implementation.
module.exports = { entry: './src/index.js', output: { filename: 'main.js', path: Path.resolve (__dirname, 'dist'), // Customize the output filename 1. AssetModuleFilename to modify the template string assetModuleFilename: 'images/[hash][ext][query]' }, module: { rules: [ { test: / \. (PNG | JPG | GIF) $/, / / need from asset loader to exclude from new URL processing asset dependency: {not: [' URL ']}, use: [{loader: 'url-loader', options: {limit: 8192,}},], // Want to stop processing of the current asset module and start processing again to avoid duplicate asset type: 'javascript/auto'}, // Resource Configuration {test: /\.png/, type: 'asset/resource'}, // Customize the output file name 2. Send some resources to the specified directory. This applies only to asset and asset/resource module types {test: /\.html/, type: 'asset/resource', generator: { filename: 'static/[hash][ext][query]' } }, { test: /\.svg/, type: 'asset/inline', // Custom data URI generator, all.svg files will be encoded with the mini-svG-data-URI package generator: {dataUrl: content => { content = content.toString(); return svgToMiniDataURI(content); } }, { test: /\.txt/, type: 'asset/source', }, { test: /\.doc/, // General resource type, WebPack will automatically choose between resource and inline by default: files smaller than 8KB will be treated as inline module type, otherwise it will be treated as Resource module type: 'asset', parser: { dataUrlCondition: { maxSize: 4 * 1024 // 4kb } } } ] }, }Copy the code
  • The resource resources
import mainImage from './images/main.png';

img.src = mainImage; // '/dist/151cfcfa1bd74779aadb.png'
Copy the code
  • The inline resources
import metroMap from './images/metro.svg'; block.style.background = `url(${metroMap})`; // url(data:image/svg+xml; base64,PHN2ZyB4bWxucz0iaHR0cDo... vc3ZnPgo=)Copy the code
  • The source of resources

src/example.txt

Hello world
Copy the code

src/index.js

import exampleText from './example.txt';

block.textContent = exampleText; // 'Hello world'
Copy the code
  • The url resources

Webpack also creates resource modules when using new URL(‘./path/to/asset’, import.meta. URL).

src/index.js

const logo = new URL('./logo.svg', import.meta.url);
Copy the code

Depending on the target in your configuration, Webpack will compile the above code into different results:

// target: web
new URL(__webpack_public_path__ + 'logo.svg', document.baseURI || self.location.href);

// target: webworker
new URL(__webpack_public_path__ + 'logo.svg', self.location);

// target: node, node-webkit, nwjs, electron-main, electron-renderer, electron-preload, async-node
new URL(__webpack_public_path__ + 'logo.svg', require('url').pathToFileUrl(__filename));
Copy the code