如何使Webpack忽略特定require

667 阅读1分钟

背景

项目中有一特殊需求,需要webpack忽略特殊协议头类型的require,例如 require('special://xxx.xxx.xxx')

解决方法

  1. webpack收集资源阶段,取消添加指定依赖
  2. webpack预拉取资源阶段,取消添加指定依赖

修改webpack源码 Compilation

node_modules/webpack/lib/Compilation.js

/**
 *
 * @param {string} context context path for entry
 * @param {Dependency} entry entry dependency being created
 * @param {string} name name of entry
 * @param {ModuleCallback} callback callback function
 * @returns {void} returns
 */
addEntry(context, entry, name, callback) {
    // 收集资源阶段,取消添加指定依赖
    if (entry.request.startsWith('special://')) return callback();
    this.hooks.addEntry.call(entry, name);

    const slot = {
            name: name,
            // TODO webpack 5 remove `request`
            request: null,
            module: null
    };

    if (entry instanceof ModuleDependency) {
            slot.request = entry.request;
    }

    // TODO webpack 5: merge modules instead when multiple entry modules are supported
    const idx = this._preparedEntrypoints.findIndex(slot => slot.name === name);
    if (idx >= 0) {
            // Overwrite existing entrypoint
            this._preparedEntrypoints[idx] = slot;
    } else {
            this._preparedEntrypoints.push(slot);
    }
    this._addModuleChain(
            context,
            entry,
            module => {
                    this.entries.push(module);
            },
            (err, module) => {
                    if (err) {
                            this.hooks.failedEntry.call(entry, name, err);
                            return callback(err);
                    }

                    if (module) {
                            slot.module = module;
                    } else {
                            const idx = this._preparedEntrypoints.indexOf(slot);
                            if (idx >= 0) {
                                    this._preparedEntrypoints.splice(idx, 1);
                            }
                    }
                    this.hooks.succeedEntry.call(entry, name, module);
                    return callback(null, module);
            }
    );
}

/**
 * @param {string} context context path string
 * @param {Dependency} dependency dep used to create module
 * @param {ModuleCallback} callback module callback sending module up a level
 * @returns {void}
 */
prefetch(context, dependency, callback) {
    // 预拉取资源阶段,在添加模块链时,取消添加指定依赖
    this._addModuleChain(
            context,
            dependency,
            module => {
                    module.prefetched = true;
            },
            callback
    );
}

_addModuleChain(context, dependency, onModule, callback) {
    // 取消添加指定依赖
    if (dependency.request.startsWith('special://')) return callback();
    const start = this.profile && Date.now();
    const currentProfile = this.profile && {};

}`