preface

There is a period of time did not do accumulation and learning, the recent learning content will be gradually updated.

Webpack should write a series, from the initial => in-depth => actual combat.

Follow “Hello FE” for more easy-to-understand content.

Creating a Demo (using Lerna)

Here we create a Monorepo using Lerna. For those of you who are not familiar with Monorepo and Lerna, check out this article: Large Front-end Project Management – Monorepo.

Run the following command:

yarn global add lerna
mkdir demo && cd demo
lerna init
Copy the code

Get a Monorepo project with a directory structure like this:

.├ ── ├─ package. ├─ ├─ ├.json ├─ ├.txtCopy the code

Then create a BASIC folder in the Packages directory, meaning this is a basic Demo.

Create three files in the Packages /basic directory: index.html, index.js, func.js.

<! -- index.html -->
<! DOCTYPEhtml>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
    <title>basic webpack demo</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="./bundle.js"></script>
  </body>
</html>
Copy the code
// func.js
function show(content) {
  document.querySelector('#app').innerHTML = `Hello, ${content}! `;
}

module.exports = show;
Copy the code
// index.js
const show = require('./func');

show('Webpack');
Copy the code

The bundle.js file is not available at this time, so the web page cannot display its content properly at this time.

You will later need to use Webpack to package index.js and func.js to generate the bundle.js you eventually need.

Run the following command:

cd packages/basic
yarn init
yarn add webpack webpack-cli --dev
Copy the code

After basic is initialized and Webpack is installed, you need to configure the Webpack and package it to generate the bundle.js that you eventually need.

Create the Webpack configuration file webpack.config.js in BASIC.

// webpack.config.js
const path = require('path');

module.exports = {
  // Developer tools do not require debugging
  devtool: false.// Development mode does not compress code
  mode: 'development'.// Import file
  entry: './index.js'.output: {
    // Output the file name
    filename: 'bundle.js'.// Output file path
    path: path.join(__dirname, '/'),}};Copy the code

Then open package.json and add a NPM scripts.

// package.json
{
  "name": "basic"."version": "1.0.0"."main": "index.js"."repository": "https://github.com/wjq990112/Learning-Webpack"."author": "wjq990112"."license": "MIT"."scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "webpack": "^ 5.19.0"."webpack-cli": "^ 4.4.0"}}Copy the code

Run the following command:

yarn build
Copy the code

Use Webpack to package index.js and func.js.

Once packaged, basic generates one more bundle.js. At this point, open the index.html in your browser, and the page will say Hello, Webpack! .

Beautify Demo (using Loader)

Now that the basic Demo has been created, let’s beautify the page to make Hello, Webpack! This passage is horizontally centered.

Webpack has a Loader mechanism that can be used to convert non-javascript files into code that can be used in JavaScript.

Create a style file index. CSS in basic:

/* index.css */
#app {
  text-align: center;
}
Copy the code

In index.js we introduce:

// index.js
require('./index.css');

const show = require('./func');

show('Webpack');
Copy the code

In this case, an error occurs when you run YARN Build, because Webpack does not support CSS. You need to use the corresponding Loader to convert CSS.

Execute the following script:

yarn add style-loader css-loader --dev
Copy the code

Then modify webpack.config.js:

// webpack.config.js
const path = require('path');

module.exports = {
  // Developer tools do not require debugging
  devtool: false.// Development mode does not compress code
  mode: 'development'.// Import file
  entry: './index.js'.output: {
    // Output the file name
    filename: 'bundle.js'.// Output file path
    path: path.join(__dirname, '/'),},module: {
    rules: [{// Matches files with the suffix.css
        test: /\.css$/,
        use: ['style-loader'.'css-loader'],},],},};Copy the code

All files with the.css suffix are matched by the re, and the CSS files are handed to CSS-loader and style-loader for processing.

  • useThe order of execution ofFrom the back forwardperform
  • loaderPassing in parameters is supported in two ways:
    1. UrlSearchParams
    2. Options Object

So there should be a first. The CSS at the end of the file to the CSS – loader for processing, then passed on to style – loader will be injected into the bundle, js, through the DOM manipulation in the < head > < / head > tag in the injection pattern.

Run the following command:

yarn build
Copy the code

If you open bundle.js, you’ll find a very long section of code that handles the style, injecting the style code into the tag as a

tag.

Back to page, Hello, Webpack! Horizontal center is achieved. If you open the console, you can see that the tag has a

tag, which contains the contents of the index.css.

Core code:

function insertStyleElement(options) {
  var style = document.createElement('style');
  var attributes = options.attributes || {};

  if (typeof attributes.nonce === 'undefined') {
    var nonce = true ? __webpack_require__.nc : 0;

    if(nonce) { attributes.nonce = nonce; }}Object.keys(attributes).forEach(function (key) {
    style.setAttribute(key, attributes[key]);
  });

  if (typeof options.insert === 'function') {
    options.insert(style);
  } else {
    var target = getTarget(options.insert || 'head');

    if(! target) {throw new Error(
        "Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.",); } target.appendChild(style); }return style;
}
Copy the code

But there are two problems with injecting style code into HTML in this way:

  1. increasedDOMoperation
  2. bundle.jsCode size increases

Given the problem, is it possible to extract the CSS file separately and not bundle it into bundle.js?

Optimize Demo (using Plugin)

At this point, you need to optimize bundle.js, separate the CSS files from the bundle.js, and then import the CSS style files separately.

Webpack has a plugin mechanism that can be used to process code at certain stages of the packaging process.

To separate the style files, you need to use a plugin: MiniCssExtractPlugin.

Run the following command:

yarn add mini-css-extract-plugin --dev
Copy the code

Install the MiniCssExtractPlugin and make some changes to webpack.config.js:

// webpack.config.js
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  // Developer tools do not require debugging
  devtool: false.// Development mode does not compress code
  mode: 'development'.// Import file
  entry: './index.js'.output: {
    // Output the file name
    filename: 'bundle.js'.// Output file path
    path: path.join(__dirname, '/'),},module: {
    rules: [{// Matches files with the suffix.css
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],},],},plugins: [new MiniCssExtractPlugin()],
};
Copy the code

After you run yarn Build, a main.css file is added to the current directory.

Go back to index.html and introduce the separate main.css:

<! -- index.html -->
<! DOCTYPEhtml>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
    <title>basic webpack demo</title>
    <link rel="stylesheet" href="./main.css" />
  </head>
  <body>
    <div id="app"></div>
    <script src="./bundle.js"></script>
  </body>
</html>
Copy the code

Back on the page, Hello, Webpack! Horizontal center is also achieved. Open the console and you can see that the style main.css has been introduced correctly.