关于webpack:webpack-起步

52次阅读

共计 6977 个字符,预计需要花费 18 分钟才能阅读完成。

webpack

webpack 就是一个前端资源打包工具,它依据模块的依赖关系进行动态剖析,而后将这些模块依照指定的规定生成对应动态资源。

根本应用

在本地装置 webpack

yarn add webpack webpack-cli --dev

文件目录,创立 webpack.config.js 配置文件(在 webpack v4 中,能够毋庸任何配置,然而大多数我的项目会须要很简单的设置)。

const path = require("path");

module.exports = {
  /**
   * 默认值为 production
   * development 优化打包速度,增加一些调试过程须要的辅助
   * production 优化打包后果
   **/
  mode: "development",
  entry: "./src/main.js", // 入口文件
  output: {
    filename: "bundle.js", // 输入文件名
    path: path.join(__dirname, "dist"), // 输入文件门路
  },
};

运行打包命令

yarn webpack

资源模块加载

Webpack 默认只能解决 js 文件,非 js 文件通过 loader 加载解决

文件资源

安装文件资源对应 loader

yarn add css-loader style-loader --dev

文件引入

// main.js

import createHeading from "./heading.js";
import "./main.css";

const heading = createHeading();

document.body.append(heading);

webpack 配置文件

通过 css-loader 实现对 css 文件的解决,还须要 style-loader 将打包后的 css 文件引入页面

留神:loader 的记录机制是从后往前,所以数组中 css loader 在后先应用,style loader 在后,后应用

const path = require("path");

module.exports = {
  mode: "none",
  entry: "./src/main.js",
  output: {
    filename: "bundle.js",
    path: path.join(__dirname, "dist"),
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
};

图片资源

因为 index.html 没有生成到 dist 目录,而是放在我的项目的根目录下,所以把我的项目根目录作为网站根目录,而 webpack 会默认认为所有打包后果都放在网站的根目录上面,导致在根目录下查找图片资源。解决办法配置 publicPath: 'dist/'

webpack 打包时遇到图片文件,依据配置文件配置,匹配到文件加载器,文件加载器开始工作,先将导入的文件 copy 到输入目录,而后将文件 copy 到输入目录过后的门路,作为以后模块的返回值返回, 这样资源就被公布进去了。

装置图片资源对应 loader

yarn add file-loader --dev

文件引入

import createHeading from "./heading.js";
import "./main.css";
import icon from "./icon.png";

const heading = createHeading();

document.body.append(heading);

const img = new Image();
img.src = icon;
document.body.append(img);

webpack 配置文件

const path = require("path");

module.exports = {
  mode: "none",
  entry: "./src/main.js",
  output: {
    filename: "bundle.js",
    path: path.join(__dirname, "dist"),
    publicPath: "dist/",
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /.png$/,
        use: "file-loader",
      },
    ],
  },
};

URL 资源

data urls 是非凡的 url 协定,能够用来间接示意一个文件,传统 url 要求服务器有一个对应文件,而后咱们通过申请这个地址失去这个对应文件。而 data url 是一种以后 url 就能够间接示意文件内容的形式,这种 url 中的文本蕴含文件内容,应用时不会发送任何 http 申请。

html 内容:data:text/html;charset=UTF-8,<h1>xxx</h1>

png 类型文件:data:image/png;base64,iVBORw0KGgoAAAANSUhE...

装置资源对应 loader

yarn add url-loader --dev

webpack 配置文件

  ...
  module: {
    rules: [
      {
        test: /.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /.png$/,
        use: {
          loader: "url-loader",
          options: {limit: 10 * 1024, // 对于小于 10kb 的图片资源应用 url-loader, 大于则应用 file-loader},
        },
      },
    ],
  },

罕用加载器分类

  • 编译转换类
  • 文件操作类
  • 代码查看类

webpack 与 es2015

webpack 因为模块打包须要,所以解决了 import 和 export,然而并不能转化代码中其余的 es6 个性

装置资源对应 loader

yarn add babel-loader @babel/core @babel/preset-env --dev
  module: {
    rules: [
      {
        test: /.js$/,
        use: {
          loader: "babel-loader",
          options: {presets: ["@babel/preset-env"],
          },
        },
      },
      {
        test: /.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /.png$/,
        use: {
          loader: "url-loader",
          options: {limit: 10 * 1024, // 对于小于 10kb 的图片资源应用 url-loader, 大于则应用 file-loader},
        },
      },
    ],
  },

模块加载形式

模块加载的形式有遵循 ES Modules 规范的 import 申明,遵循 CommonJS 规范的 require 函数,遵循 AMD 规范的 define 函数和 require 函数

除了下面形式,触发模块加载形式还有 css 款式代码中的 url 函数和 @import 指令,html 代码中图片标签的 src 属性

html 中的 src 属性触发模块加载

yarn add html-loader --dev
{
  test:/.html$/,
  use:{loader:'html-loader'}
}

然而 html-loader 只能解决 html 下 img:src 属性,其余额定属性通过 attrs 配置

{
  test:/.html$/,
  use:{
    loader:'html-loader', // 默认只能解决 html img src 属性,其余额定属性通过 attrs 配置
    options:{attrs:['img:src','a:href']
    }
  }
}

开发一个 loader

webpack 加载资源过程相似于工作管道,能够在加载过程中顺次应用多个 loader,然而最终后果必须是 js 代码。

每个 webpack loader 都须要导出一个函数,输出就是加载到的资源文件的内容,输入就是此次加工过后的后果。

const marked = require("marked");

module.exports = (source) => {const html = marked(source);
  return html;
};
module: {
  rules: [
    {
      test: /.md$/,
      use: [
        "html-loader",
        "./md-loader", // 模块名称或文件门路,相似 nodejs 的 require
      ],
    },
  ];
}

插件机制

loader 专一实现资源模块加载,plugin 解决其余自动化工作,加强 webpack 自动化能力

主动革除目录插件

装置扩大包

yarn add clean-webpack-plugin --dev
const path = require("path");
const {CleanWebpackPlugin} = require("clean-webpack-plugin");

module.exports = {
  mode: "none",
  entry: "./src/main.js",
  output: {
    filename: "bundle.js",
    path: path.join(__dirname, "dist"),
    publicPath: "dist/",
  },
  module: {
    rules: [...],
  },
  plugins: [new CleanWebpackPlugin()],
};

主动生成 HTML

装置扩大包

yarn add html-webpack-plugin --dev

dist 下生成 html,解决以前根下 html 中的引入门路须要通过 publicpath 申明硬编码的问题。

const path = require("path");
const {CleanWebpackPlugin} = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "none",
  entry: "./src/main.js",
  output: {
    filename: "bundle.js",
    path: path.join(__dirname, "dist"),
    // publicPath: "dist/",
  },
  plugins: [new CleanWebpackPlugin(), new HtmlWebpackPlugin()],
};

自定义元数据

const path = require("path");
const {CleanWebpackPlugin} = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "none",
  entry: "./src/main.js",
  output: {
    filename: "bundle.js",
    path: path.join(__dirname, "dist"),
  },
  plugins: [new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      title: "webpack plugin sample",
      meta: {viewport: "width=device-width",},
      template: "./src/index.html",
    }),
  ],
};

模板文件

<!--./src/index.html-->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Webpack</title>
  </head>
  <body>
    <div class="container">
      <!-- 拜访插件配置数据 -->
      <h1><%= htmlWebpackPlugin.options.title %></h1>
    </div>
  </body>
</html>

同时输入多个页面文件

const path = require("path");
const {CleanWebpackPlugin} = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "none",
  entry: "./src/main.js",
  output: {
    filename: "bundle.js",
    path: path.join(__dirname, "dist"),
  },
  plugins: [new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      title: "webpack plugin sample",
      meta: {viewport: "width=device-width",},
      template: "./src/index.html",
    }),
    new HtmlWebpackPlugin({filename: "about.html",}),
  ],
};

动态文件拷贝插件

yarn add copy-webpack-plugin --dev
const CopyWebpackPlugin = require("copy-webpack-plugin");

plugins: [
  // 参数数组,指定拷贝的文件门路(通配符,目录,相对路径)new CopyWebpackPlugin({patterns: ["public"],
  }),
];

插件机制工作原理

webpack plugin 是通过钩子机制实现。

钩子机制相似于 web 中的事件。在 webpack 工作过程中会有很多环节,为了便于插件的扩大,webpack 简直给每一个环节都埋下了钩子,这样咱们在开发插件时,能够通过往这些不同的节点下来挂载不同工作,就能够轻松扩大 webpack 的能力。

开发一个插件

webpack 要求插件必须是一个函数或者是一个蕴含 apply 办法的对象,个别咱们都会把插件定义为一个类型,而后再这个类型中定义一个 apply 办法

定义一个插件往钩子上挂载工作,这个插件用于革除 bundle.js 中无用的正文

MyPlugin 文件

module.exports = class MyPlugin {apply(compiler) {
    // 此办法在 webpack 启动时主动被调用,compile 配置对象,配置信息

    console.log("MyPlugin 启动");

    // 通过 hooks 属性拜访钩子 emit
    // 参考:https://webpack.docschina.org/api/compiler-hooks/
    // tap 办法注册钩子函数(参数 1: 插件名称,参数 2: 挂载到钩子上的函数)

    compiler.hooks.emit.tap("MyPlugin", (compilation) => {
      // compilation 能够了解为此次打包的上下文, 所有打包过程产生的后果都会放到这个对象中
      // compilation.assets 属性是个对象,用于获取行将写入目录当中的资源文件信息

      for (const name in compilation.assets) {// console.log("文件名称:",name); 如图
        // console.log("文件内容:",compilation.assets[name].source());

        if (name.endsWith(".js")) {
          // 获取内容
          const contents = compilation.assets[name].source();

          // 替换内容
          const withoutComments = contents.replace(/\/\*\*+\*\//g, "");

          // 笼罩老内容
          compilation.assets[name] = {source: () => withoutComments,
            size: () => withoutComments.length, // 返回内容的大小,webpack 要求必须加};
        }
      }
    });
  }
};

配置文件

const path = require("path");
const {CleanWebpackPlugin} = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const myPlugin = require("./MyPlugin.js");

module.exports = {
  mode: "none",
  entry: "./src/main.js",
  output: {
    filename: "bundle.js",
    path: path.join(__dirname, "dist"),
    // publicPath: "dist/",
  },

  plugins: [new CleanWebpackPlugin(), new myPlugin()],
};

正文完
 0