webpack 实现 CopyWebpackPlugin

44 篇文章 21 订阅
36 篇文章 21 订阅

CopyWebpackPlugin 将已经存在的单个文件或整个目录复制到构建目录。

准备工作

npm i webpack webpack-cli

创建如下项目目录

├── plugins                          # 编译打包后的输出目录
├── public                           # 静态资源
│   │── index.css
│   │── index.html
│   └── reset.css
├── src
│   └── reset.js
├── .gitignore
├── package.json
├── package-lock.json
└── webpack.config.js

代码实现

webpack.config.js

const CopyWebpackPlugin = require('./plugin/CopyWebpackPlugin');

module.exports = {
  mode: 'production',

  output: {
    clean: true,
  },

  plugins: [
    new CopyWebpackPlugin({
      form: 'public',
      to: 'css',
      ignore: ['**/index.html'],
    }),
  ],
};

plugin/CopyWebpackPlugin.js

const { validate } = require('schema-utils');
const globby = require('globby');
const path = require('path');

const schema = {
  type: 'object',
  properties: {
    form: {
      type: 'string',
    },
    to: {
      type: 'string',
    },
    ignore: {
      type: 'array',
    },
  },
  additionalProperties: false, // 是否允许不存在的选项传入
};

class CopyWebpackPlugin {
  constructor(options = {}) {
    // 校验插件options
    validate(options, schema, {
      name: 'CopyWebpackPlugin',
    });
    this.options = options;
  }

  apply(compiler) {
  	// 获取操作文件的对象
    const fs = compiler.outputFileSystem;
    
    // 绑定到 “thisCompilation” 钩子,
    // 以便进一步绑定到 compilation 过程更早期的阶段
    compiler.hooks.thisCompilation.tap('CopyWebpackPlugin', (compilation) => {
      // 绑定到 “additionalAssets” 钩子,为 compilation 创建额外 asset
      compilation.hooks.additionalAssets.tapAsync('CopyWebpackPlugin', async (callback) => {
        // 1. 获取ignore后的文件 paths
        const { form, ignore } = this.options;
        // to 默认打包目的根目录
        const to = this.options.to ? this.options.to : '.';

        // 运行指令的上下文
        const { context } = compiler.options;
        // 获取 form 的绝对地址
        const absoluteForm = path.isAbsolute(form) ? form : path.resolve(context, form);

        // 获取 ignore 后的匹配目录文件路径
        const paths = await globby(absoluteForm, { ignore });

        // 2. 读取 paths 文件内容
        const files = paths.map((absolutePath) => {
          // 读取文件
          const data = fs.readFileSync(absolutePath);

          // 获取文件名
          const filename = path.basename(absolutePath);

          // filename 和 to 结合,获取文件path
          const filePath = path.join(to, filename);
          return {
            data,
            filename: filePath,
          };
        });
        // 3. 创建webpack格式的资源,并输入

        // webpack 模块实例,可以通过 compiler 对象访问,
        // 这样确保使用的是模块的正确版本
        // (不要直接 require/import webpack)
        const { webpack } = compiler;

        // RawSource 是其中一种 “源码”("sources") 类型,
        // 用来在 compilation 中表示资源的源码
        const { RawSource } = webpack.sources;

        // 向 compilation 添加新的资源,
        // 这样 webpack 就会自动生成并输出到 output 目录
        files.forEach((file) => compilation.emitAsset(file.filename, new RawSource(file.data)));

        callback();
      });
    });
  }
}

module.exports = CopyWebpackPlugin;

验证测试

执行 npx webpack,可以看到打包结果如下,符合期待。
在这里插入图片描述



源码:https://gitee.com/yanhuakang/webpack-demos/tree/master/proficient/step_5-CopyWebpackPlugin

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Webpack 实现 Code Splitting 的方式主要有以下几种: 1. 基于入口点(Entry Points)的 Code Splitting:通过将应用程序拆分为多个入口点,每个入口点都可以生成一个独立的代码块,从而实现 Code Splitting。可以使用 Webpack 的 `entry` 配置选项来指定多个入口点,例如: ```js module.exports = { entry: { app: './src/app.js', vendor: './src/vendor.js' }, // ... } ``` 在上面的例子中,`app` 和 `vendor` 分别是两个入口点,它们可以生成独立的代码块。 2. 基于模块(Module)的 Code Splitting:通过将应用程序中的模块拆分为多个代码块,从而实现 Code Splitting。可以使用 Webpack 的 `import()` 函数来实现基于模块的 Code Splitting,例如: ```js function loadComponent() { // 动态加载异步模块 return import('./components/MyComponent.vue') } // 使用异步组件 Vue.component('my-component', () => ({ // 异步加载组件 component: loadComponent(), // 加载组件时显示的占位符 loading: LoadingComponent, // 加载组件失败时显示的占位符 error: ErrorComponent, // 组件加载成功后的延迟时间 delay: 200, // 最长等待时间 timeout: 10000 })) ``` 在上面的例子中,`loadComponent()` 函数返回一个异步加载的模块,可以通过 `import()` 函数来加载模块。然后,在组件中使用异步组件来加载动态组件。 3. 基于运行时(Runtime)的 Code Splitting:通过将应用程序的代码分成多个块,并在运行时动态加载这些代码块,从而实现 Code Splitting。可以使用 Webpack 的 `require.ensure()` 函数来实现基于运行时的 Code Splitting,例如: ```js function loadComponent() { // 动态加载异步模块 require.ensure(['./components/MyComponent.vue'], function() { // 加载成功后的回调函数 const MyComponent = require('./components/MyComponent.vue') // 渲染组件 new Vue({ el: '#app', render: h => h(MyComponent) }) }, function() { // 加载失败后的回调函数 }, 'my-component') } ``` 在上面的例子中,`require.ensure()` 函数用于异步加载模块,并在加载成功后执行回调函数。第三个参数 `'my-component'` 表示这个代码块的名称,用于指定 Webpack 生成的代码块文件名。 需要注意的是,虽然这些方式都可以实现 Code Splitting,但它们的实现方式和使用场景有所不同。因此,在实际开发中,应该根据具体的需求来选择合适的方式来实现 Code Splitting。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__畫戟__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值