webpack 依赖管理

webpack 依赖管理

webpack 提供的模块加载方式很多,ES2015 的静态加载方式是官方推荐的,但有时需要加载大批量的模块,就可以使用 webpack 模块方法的 require.context

需求

假设有这么一个项目:

src/
	packages/
		one.js
		tow.js
	app.js

其中 app.js 是主文件,主文件需要加载所有 packages 文件夹下的文件。

为了测试方便,one.jstow.js 默认导出一个函数并打印一句话:

/**
 * @file one.js
 * path: src/packages/one.js
 */

export default function one() {
  console.log("this is one");
}
/**
 * @file tow.js
 * path: src/packages/tow.js
 */

export default function tow() {
  console.log("this is tow");
}

模块上下文

要想在 src/app.js 中导入整个 packages 需要创建一个 模块上下文,模块上下文具有目标目录下所有模块的引用。

创建一个模块上下文使用 require.context 方法:

require.context(directory, (useSubdirectories = false), (regExp = /^\.\//));

它有三个参数:

  • directory:要搜索的文件夹目录;
  • useSubdirectories:是否搜索子目录;
  • regExp:过滤文件的正则表达式。

尝试在 src/app.js 中创建模块上下文:

/**
 * @file app.js
 * path: src/app.js
 */

const context = require.context("./packages", true, /\.js$/);

模块上下文提供以下 API 使用:

  • context.resolve(key):函数,传入请求的模块路径得到模块 id,模块 id 和路径很像;
  • context.keys():函数,返回被模块上下文处理请求的数组;
  • context.id:当前模块上下文的模块 id。
  • context(key):函数,传入模块请求,返回指定模块。

都使用看看:

修改 src/app.js

/**
 * @file app.js
 * path: src/app.js
 */

const context = require.context("./packages", true, /\.js$/);

// 使用 id
console.log(`id:`, context.id, `\n`);

// 使用 keys
console.log(`keys:`, context.keys(), `\n`);

// 使用 resolve

console.log(`resolve:`);
context.keys().forEach((key) => console.log(context.resolve(key)));

console.log(`\nmodules:`);

context.keys().forEach((key) =>
  /* 访问的模块需要使用 .default 访问默认导出 */
  context(key).default()
);

打包执行

安装 webpack 和 webpack-cli 打包测试:

npm install --save webpack webpack-cli

然后添加 webpack.config.js 到根目录:

/**
 * @file webpack.config.js
 */

const path = require("path");

module.exports = {
  mode: "development",
  entry: "./src/app.js",
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, "dist"),
  },
};

接着执行命令(windows 下):

npx webpack web; node ./dist/bundle.js

可以看到控制台输出为:

id: ./src/packages sync recursive \.js$

keys: [ './one.js', './tow.js' ]

resolve:
./src/packages/one.js
./src/packages/tow.js

modules:
this is one
this is tow

观察可知:

  • id 为模块上下文的相关信息组成;
  • keys 包含了引入的模块路径;
  • resolve 解析的是模块基于项目的路径;
  • 使用模块上下文可以直接访问模块,默认导出为模块的 default 属性。

在 Vue 中使用

使用 Vue 代码

假定项目目录如下:

src/
	packages/
		One.vue
		Tow.vue
	VueApp.vue

其中 src/packages/One.vue 内容修改为:

<script>
  /**
   * @file One.vue
   * path: src/packages/One.js
   */
  export default {
    name: "One",
  };
</script>
<template>
  <p>this is One</p>
</template>

src/packages/Tow.vue 的修改类似,不在赘述,注意组件名 name 不要相同。

导入整个 src/packages 文件夹里的 Vue 文件

src/VueApp.vue 文件中,编写以下代码:

<script>
  /**
   * @file VueApp.vue
   * path: src/VueApp.vue
   */

  /** 模块上下文,获取 src/packages/ 文件夹下所有的 Vue 文件 */
  const context = require.context("./packages", true, /\.vue$/);

  /** 组件包,使用组件名作为键,组件作为值填充 */
  const packages = context.keys().reduce((prev, key) => {
    const Component = context(key).default;
    prev[Component.name] = Component;

    return prev;
  }, {});

  export default {
    components: { ...packages },
    data() {
      return {
        ComponentNames: Object.keys(packages),
      };
    },
  };
</script>
<template>
  <div>
    <h2>Vue Components!</h2>

    <!-- 使用 Component 组件渲染 packages 下的所有组件 -->
    <Component v-for="name in ComponentNames" :key="name" :is="name" />

    <p>packages 文件夹下所有组件的名称为:{{ ComponentNames }}</p>
  </div>
</template>

在你的脚手架中引入这个这个组件,你可以看到动态渲染了 src/packages/ 文件夹下的所有 Vue 组件。

在 React 中使用

假定项目文件夹如下:

src/
	packages/
		One.jsx
		Tow.jsx
	ReactApp.jsx

使用 React 代码

修改 src/packages/One.jsx 文件内容如下:

/**
 * @file src/packages/One.jsx
 */
import React from "react";

export default function One() {
  return <p>this is One</p>;
}

src/packages/Tow.jsx 文件类似,不再赘述。

导入整个 src/packages 文件夹里的 jsx 文件

src/ReactApp.jsx 中编写以下代码:

/**
 * @file ReactApp.jsx
 * path: src/ReactApp.jsx
 */

import React from "react";

/** 模块上下文,获取 src/packages/ 文件夹下所有的 jsx 文件 */
const context = require.context("./packages", true, /\.jsx$/);

/** 组件包 */
const packages = context.keys().map((key) => context(key).default);

export default function ReactApp() {
  return (
    <section>
      <h2>React Components!</h2>

      {packages.map((Component) => (
        <Component key={Component.name} />
      ))}

      <p>packages 文件夹下所有组件的名称为:{packages.map((v) => v.name).join(",")}</p>
    </section>
  );
}

这样 src/ReactApp.jsx 组件就可以渲染所有 src/packages/ 文件夹下的内容了。

参考:

Dependency Management

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值