[ webpack | 青训营笔记]

57 阅读4分钟

Webpack 的本质

Webpack 是一个现代 JavaScript 应用程序的 模块打包器。它的本质是通过分析应用程序中的模块依赖关系,将不同类型的资源(如 JavaScript、CSS、图片等)打包成最终浏览器可以加载的文件。它不仅是一个打包工具,还具备了一些强大的功能,如模块处理、代码拆分、静态资源管理等。Webpack 基本上将开发过程中生成的各种资源文件(包括代码和资源)经过不同的处理,最终生成可以在浏览器中运行的优化代码。

Webpack 的核心概念:
  • 入口(Entry):指定应用程序的入口文件,Webpack 从这个文件开始,分析项目的依赖关系树。
  • 输出(Output):定义打包后的文件存放路径和命名规则。
  • 加载器(Loader):加载器使 Webpack 能够处理非 JavaScript 文件(如 CSS、图片、字体等),并将它们转换成 JavaScript 模块。
  • 插件(Plugin):插件用于扩展 Webpack 的功能,执行如打包优化、代码压缩、环境变量注入等任务。
  • 模块(Module):Webpack 会把应用程序中的每个资源都视为一个模块,进行依赖管理。

Webpack 定义解析

Webpack 是一个 JavaScript 应用程序的构建工具,主要功能是 将模块和资源打包,并生成最终浏览器可以执行的静态文件。Webpack 可以帮助开发者将多个模块(如 JavaScript 文件、CSS 文件、图片等)组织成一个或多个输出文件,通过智能优化提高网页加载性能。

Webpack 的工作方式可以通过以下几个阶段来解释:

  1. 初始化:Webpack 根据配置文件分析项目的依赖关系,识别所有的模块。
  2. 编译阶段:Webpack 利用 加载器(Loaders) 对非 JavaScript 文件进行转化,将它们转化成浏览器可以理解的模块。
  3. 优化阶段:使用 插件(Plugins) 进行各种优化,例如压缩文件、提取公共模块、自动生成 HTML 文件等。
  4. 打包输出:最终,Webpack 将所有处理后的模块打包成一个或多个输出文件,准备部署到生产环境。

Webpack 的优势

Webpack 在现代前端开发中非常流行,其优势体现在以下几个方面:

  1. 模块化支持

    • Webpack 支持 JavaScript 模块化,可以根据 ES6 的 import/export 语法处理模块。
    • 支持 CommonJS、AMD 等模块化规范,甚至可以通过 require 动态加载模块。
  2. 资源打包和优化

    • 可以处理 CSS、图片、字体等各种资源,通过相应的加载器(loader)对这些资源进行转化。
    • Webpack 可以自动进行资源压缩、合并,减少 HTTP 请求,提高页面加载速度。
  3. 代码拆分(Code Splitting)

    • Webpack 允许将大型应用程序拆分成更小的代码块(chunks),按需加载,提高页面的加载速度。
    • 支持按模块、按页面、按入口进行拆分。
  4. 支持多种插件(Plugins)

    • Webpack 提供了大量的插件,支持优化、压缩、环境变量注入、自动生成 HTML 文件等功能,增强了打包的灵活性和可定制性。
  5. 热模块替换(HMR,Hot Module Replacement)

    • 在开发模式下,Webpack 可以在不刷新整个页面的情况下,实时替换代码,极大提高开发效率。
    • 热更新不仅限于 JavaScript,也可以应用到 CSS 和 HTML 中。
  6. Tree Shaking(树摇)

    • Webpack 通过分析代码的静态结构,去除未被使用的代码,减少打包文件的体积,提高加载速度。
    • 对于使用 ES6 模块的项目,Webpack 会自动进行树摇,去掉无用的代码。
  7. 配置灵活

    • Webpack 提供了高度可配置的选项,几乎所有的打包行为都可以通过配置文件来定义。
    • 可以根据开发环境和生产环境的不同需求,调整配置,达到最佳的性能优化。
  8. 社区支持和生态系统

    • Webpack 拥有一个庞大的社区和丰富的插件生态,开发者可以找到几乎任何需求的插件或资源。

webpack实验开发

Demo01: 单文件入口 (源码)

Webpack会入口文件进行打包成bundle.js.

例子, main.js 是单文件入口.

// main.js
document.write('<h1>Hello World</h1>');

index.html

<html>
  <body>
    <script type="text/javascript" src="bundle.js"></script>
  </body>
</html>

Webpack follows webpack.config.js to build bundle.js.

// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  }
};

启动服务, 访问 http://127.0.0.1:8080 .

$ webpack-dev-server

Demo02: 多文件入口(源码)

多个入口文件,实用于多个页面的应用

// main1.js
document.write('<h1>Hello World</h1>');
 
// main2.js
document.write('<h2>Hello Webpack</h2>');

index.html

<html>
  <body>
    <script src="bundle1.js"></script>
    <script src="bundle2.js"></script>
  </body>
</html>

webpack.config.js

module.exports = {
  entry: {
    bundle1: './main1.js',
    bundle2: './main2.js'
  },
  output: {
    filename: '[name].js'
  }
};

Demo03: Babel-loader (源码)

通过使用不同的loader,webpack通过调用外部的脚本或工具可以对各种各样的格式的文件进行处理(更多信息). 例如, Babel-loader Babel其实是一个编译JavaScript的平台可以将 JSX/ES6 文件转换成浏览器可以识别的js文件. 官方文档loaders.

main.jsx is a JSX 文件.

const React = require('react');
const ReactDOM = require('react-dom');
 
ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.querySelector('#wrapper')
);

index.html

<html>
  <body>
    <div id="wrapper"></div>
    <script src="bundle.js"></script>
  </body>
</html>

webpack.config.js

module.exports = {
  entry: './main.jsx',
  output: {
    filename: 'bundle.js'
  },
  module: {
    loaders:[
      {
        test: /.js[x]?$/,
        exclude: /node_modules/,
        loader: 'babel-loader?presets[]=es2015&presets[]=react'
      },
    ]
  }
};

在 webpack.config.jsmodule.loaders 区域是用来分配loader的. 像上面的代码片段使用了 babel-loader 需要安装插件 babel-preset-es2015 和 babel-preset-react to 编译成 ES6 and React. 可以用query配置参数

module: {
  loaders: [
    {
      test: /.jsx?$/,
      exclude: /node_modules/,
      loader: 'babel',
      query: {
        presets: ['es2015', 'react']
      }
    }
  ]
}

Demo04: CSS-loader (源码)

Webpack 允许你在js文件中require CSS , 通过 CSS-loader来预处理css文件.

main.js

require('./app.css');

app.css

body {
  background-color: blue;
}

index.html

<html>
  <head>
    <script type="text/javascript" src="bundle.js"></script>
  </head>
  <body>
    <h1>Hello World</h1>
  </body>
</html>

webpack.config.js

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  module: {
    loaders:[
      { test: /.css$/, loader: 'style-loader!css-loader' },
    ]
  }
};

但是,你需要使用2中loaders来转换CSS 文件. 第一个是 CSS-loader 来读取CSS文件, 另外一个是Style-loader 是将style样式插入到html中。 中间用!连接

启动服务后, index.html 有内部样式.

<head>
  <script type="text/javascript" src="bundle.js"></script>
  <style type="text/css">
    body {
      background-color: blue;
    }
  </style>
</head>

Demo05: Image loader (源码)

Webpack 允许你在js文件中require图片 , 通过 url-loader和file-loader来预处理图片文件.

main.js

var img1 = document.createElement("img");
img1.src = require("./small.png");
document.body.appendChild(img1);
 
var img2 = document.createElement("img");
img2.src = require("./big.png");
document.body.appendChild(img2);

index.html

<html>
  <body>
    <script type="text/javascript" src="bundle.js"></script>
  </body>
</html>

webpack.config.js

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  module: {
    loaders:[
      { test: /.(png|jpg)$/, loader: 'url-loader?limit=8192' }
    ]
  }
};