Webpack学习 | 青训营

55 阅读4分钟

什么是Webpack

Webpack 是一种用于构建 JavaScript 应用程序的静态模块打包器,它能够以一种相对一致且开放的处理方式,加载应用中的所有资源文件(图片、CSS、视频、字体文件等),并将其合并打包成浏览器兼容的 Web 资源文件。

image.png Webpack可以忽略具体资源类型之间的差异,将所有代码/非代码文件都统一看作Module——模块对象,以相同的加载、解析、依赖管理、优化、合并流程实现打包,并借助Loader、Plugin两种开放接口将资源差异逻辑转交由社区实现,实现统一资源构建模型。借助 Loader,Webpack 几乎可以用任意方式处理任意类型的资源,例如可以用 Less、Stylus、Sass 等预编译 CSS 代码。

webpack基本使用

webpack的核心概念

Webpack 是一种 「配置」 驱动的构建工具,所以站在应用的角度,必须深入学习 Webpack 的各项配置规则,才能灵活应对各种构建需求。

  • Entry:入口,Webpack 执行构建的第一步将从 Entry 开始,可抽象成输入。
  • Module:模块,在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。
  • Chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。
  • Loader:模块转换器,用于把模块原内容按照需求转换成新内容。
  • Plugin:扩展插件,在 Webpack 构建流程中的特定时机会广播出对应的事件,插件可以监听这些事件的发生,在特定时机做对应的事情。

安装

npm install webpack webpack-cli -D

编辑配置文件

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

module.exports = {
  entry: './src/index.js',
  output: {
    filename: '[name].js',
    path: resolve(__dirname, 'build')
  },
  mode: 'production'
};

// a.js
export const name = 'JavaScript';
export const age = "学习Webpack";

// b.js
import * as a from './a';
export { a };

// index.js
import * as b from './b';
console.log(b.a.name);

打包后生成代码

!function(e){var n={};function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(n){return e[n]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=0)}([function(e,n,t){"use strict";t.r(n);var r={};t.r(r),t.d(r,"name",(function(){return o})),t.d(r,"age",(function(){return u}));const o="JavaScript",u="学习Webpack";console.log(r.name)}]);

借助预处理器、PostCss构建CSS工程环境

CSS 语言在过去若干年中一直在追求样式表现力方面的提升,工程化能力薄弱,例如缺乏成熟的模块化机制、依赖处理能力、逻辑判断能力等。为此,在开发现代大型 Web 应用时,通常会使用 Webpack 配合其它预处理器编写样式代码。我们如何使用CSS代码处理工具?使用css-loaderstyle-loadermini-css-extract-plugin 处理原生 CSS 文件;如何使用 Less/Sass/Stylus 预处理器;如何使用 PostCSS?

  • css-loader:该 Loader 会将 CSS 等价翻译为形如 module.exports = "${css}" 的JavaScript 代码,使得 Webpack 能够如同处理 JS 代码一样解析 CSS 内容与资源依赖;

  • style-loader:该 Loader 将在产物中注入一系列 runtime 代码,这些代码会将 CSS 内容注入到页面的 <style> 标签,使得样式生效;

  • mini-css-extract-plugin:该插件会将 CSS 代码抽离到单独的 .css 文件,并将文件通过 <link> 标签方式插入到页面中。

css-loader使用

yarn add -D css-loader

修改webpack配置,定义规则

module.exports = { 
    module: { 
        rules: [ 
            { test: /\.css$/i, 
            use: ["css-loader"],
            },
        ], 
    }, 
};

然后我们就可以执行npx webpack或其它构建命令即可,经过 css-loader 处理后还需要继续接入 style-loader 加载器。

  • style-loader 并不会对代码内容做任何修改,而是简单注入一系列运行时代码,用于将 css-loader 转译出的 JS 字符串插入到页面的 style 标签。接入时同样需要安装依赖:
yarn add -D style-loader css-loader

之后修改 Webpack 配置,定义 .css 规则:

module.exports = {
  module: {
    rules: [
      {
        test: /.css$/i,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
};

注意保持 style-loader 在前,css-loader 在后。此时样式才真正开始生效。

使用预处理器

以Less为例,安装依赖

yarn add -D less less-loader

其次,修改 Webpack 配置,添加 .less 处理规则:

module.exports = {
    module: {
        rules: [{
            test: /.less$/,
            use: [
                'style-loader',
                'css-loader',
                'less-loader'
            ]
        }]
    }
}

使用post-css

post-css实际上不是一个预处理器或后处理器,而是一个 CSS 处理工具的框架。如果你只需要编译 LESS 样式并在 Webpack 构建中使用,那么 less-loader 可能是一个不错的选择。如果你想要更广泛的 CSS 处理能力,例如自动添加浏览器前缀、优化和转换等,那么 PostCSS 是更适合的选择。当然,我们完全可以在同一个项目中同时使用两者。 PostCSS 的接入步骤也很简单,首先安装依赖:

yarn add -D postcss postcss-loader

之后添加 Webpack 配置:

module.exports = {
  module: {
    rules: [
      {
        test: /.css$/,
        use: [
          "style-loader", 
          "css-loader", 
          "postcss-loader"
        ],
      },
    ],
  }
};

不过,这个时候的 PostCSS 还只是个空壳,下一步还需要使用适当的 PostCSS 插件进行具体的功能处理,例如我们可以使用 autoprefixer 插件自动添加浏览器前缀,首先安装依赖:

yarn add -D autoprefixer

之后,修改 Webpack 配置:

module.exports = {
  module: {
    rules: [
      {
        test: /.css$/,
        use: [
          "style-loader", 
          {
            loader: "css-loader",            
            options: {
              importLoaders: 1
            }
          }, 
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                // 添加 autoprefixer 插件
                plugins: [require("autoprefixer")],
              },
            },
          }
        ],
      },
    ],
  }
};

之后,再次运行 Webpack 即可为 CSS 代码自动添加浏览器前缀。

总结

  • Webpack 不能理解 CSS 代码,所以需要使用 css-loaderstyle-loadermini-css-extract-plugin 三种组件处理样式资源;
  • Less/Sass/Stylus/PostCSS 等工具可弥补原生 CSS 语言层面的诸多功能缺失,例如数值运算、嵌套、代码复用等。