1

我知道您不能有条件require地使用 browserify 模块,因为它们是在编译时捆绑的,而不是在运行时捆绑的。有条件地剥离模块怎么样?

假设我有一个应用程序可以让您创建图片库。还可以编辑画廊(重新排序图像等)。但是画廊的渲染和剪辑是耦合的,不能完全分开。但是对于部署画廊,我不需要编辑功能,而且我知道使用了哪些模块。我想创建两个不同的包,一个具有编辑功能,一个不消除大部分编辑代码。我所做的是使用envify和 uglify 的死代码消除将我自己的代码从较小的包中排除。

之前 (thing.js)

//...some code that only the editor needs...
module.exports = thing;

之后(thing.js)

if(process.env.INCLUDE_EDITOR === 'yes') {
    //...some code that only the editor needs...
    module.exports = thing;
}

这很好用,编辑器包已经更小了。而且因为我知道另一个包永远不会使用thing它的功能,所以什么都不导出并有一个空模块是可以的。

现在问题来了。例如,如果thing.js需要一个模块,即使在消除死代码后没有人使用它pica,它仍然会被捆绑。

之前 (thing.js)

var pica = require('pica');
//...some code that uses pica...
module.exports = thing;

之后(thing.js)

if(process.env.INCLUDE_EDITOR === 'yes') {
    var pica = require('pica');
    //...some code that uses pica...
    module.exports = thing;
}

总结一下:我的包现在包含pica库,但没有人需要它。需要它的代码是死代码,但uglify显然无法理解它可以pica完全删除。

4

2 回答 2

1

我认为你所追求的是像uglifyify.

Uglifyify 为您提供了在每个文件包含在包中之前对其应用 Uglify 的“挤压”转换的好处,这意味着您可以删除条件要求的死代码路径。

请注意,您仍然希望uglifyjs在结果输出上运行。

于 2016-10-25T12:43:13.373 回答
0

我想我找到了一个足够好的解决方案。作为奖励,它不需要触及现有代码(例如添加process.env.检查)。我写了一个 browserify 转换,给定一个模块/文件列表,将它们的require调用替换为{}. 这样它们就完全从生成的包中删除了。无论如何,这只是一个黑客行为。我知道。

前:

var thing = require('./thing.js');
var pica = require('pica');

后:

var thing = {};
var pica = {};

使用https://www.npmjs.com/package/browserify-transform-tools这只是几行代码,因为它已经提供了一个makeRequireTransform帮助程序。我将在这里转储代码并建议任何人都不要使用它,除非您确切知道自己在做什么。

derequire.js

var path = require('path');
var resolve = require('resolve');
var transformTools = require('browserify-transform-tools');

var options = {
    evaluateArguments: true,
    jsFilesOnly: true
};

var cache = {};
var resolveDerequire = function(moduleName) {
    var fromCache = cache[moduleName];

    if(fromCache) {
        return fromCache;
    }

    return require.resolve(moduleName);
};

var transform = transformTools.makeRequireTransform('derequire', options, function(args, transformOptions, done) {
    var requiredModule = args[0];
    var basedir = path.dirname(transformOptions.file);

    var shouldDerequire = transformOptions.config.modules.some(function(moduleToRequire) {
        try {
            //The normal require which respects NODE_PATH.
            return require.resolve(requiredModule) === resolveDerequire(moduleToRequire);
        } catch(ex1) {
            try {
                //A local require relative to the current file.
                return resolve.sync(requiredModule, {basedir: basedir}) === resolveDerequire(moduleToRequire);
            } catch(ex2) {
                console.error(ex1, ex2);
                return false;
            }
        }
    });

    if(shouldDerequire) {
        done(null, '{}');
    } else {
        done();
    }
});


module.exports = transform;

转换的 package.json 配置

"browserify": {
    "transform": [
        "babelify",
        [
            "./derequire.js",
            {
                "modules": [
                    "pica",
                    "exif-js",
                    "./src/thing.js",
                    "components/TextEditor.jsx",
                    "lib/FileUploader.js"
                ]
            }
        ],
        "browserify-css",
        "imgurify",
        "glslify"
    ]
},
于 2016-10-24T13:05:52.530 回答