2016-10-24 2 views
1

Я знаю, что вы не можете условно require модуль с браузером, потому что они связаны во время компиляции, а не время выполнения. Как насчет условно снятия модулей?Условный компиляция/необходимость использования браузера (удаление мертвого кода)

Предположим, у меня есть приложение, которое позволяет создавать галереи изображений. Галереи также можно редактировать (переупорядочение изображений и т. Д.). Но рендеринг галереи и редактирование связаны и не могут быть полностью разделены. Но для развертывания галерей мне не нужны функции редактирования, и я знаю, какие модули используются. Я хочу создать два разных пакета: один с возможностью редактирования и один без исключения, исключив большую часть кода редактирования. То, что я сделал, это использование 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 библиотеку, но никто не требует. Код, который ему нужен, был мертвым кодом, но, возможно, угляд не может понять, что он может полностью удалить pica.

+0

Возможно, вам будет полезна ['factor-bundle'] (https://github.com/substack/factor-bundle)? – casr

+0

@casr спасибо! Я не думаю, что это можно применить здесь. Учитывая пример в документах, я хочу удалить w и z из пакета x, потому что я знаю, что 'console.log (z (5) * w (2));' никогда не будет выполнен. Тем не менее, это все равно будет в комплекте. Я как бы делаю глупые сумасшедшие вещи здесь. Но эй, я удалил 20% из не-редактора! – Prinzhorn

ответ

1

Я думаю, что вы после этого преобразования как uglifyify.

Uglifyify дает вам преимущество применения «сжатого» преобразования Uglify для каждого файла до его включения в комплект, что означает, что вы можете удалить пути мертвого кода для условных запросов.

Обратите внимание, что вы по-прежнему хотите запустить uglifyjs на результирующий вывод.

+0

Вы абсолютно правы! Это точно то, что я изначально хотел. Я буду придерживаться решения, которое у меня есть, так как это приводит к еще меньшему набору. Но uglifyify является менее взломанной версией. – Prinzhorn

+0

Это должно привести к тому же набору размеров, что и ваш пользовательский шаг преобразования, с дополнительным преимуществом автоматической работы с изменениями в проекте. Если вы получаете меньшие пакеты, чем это, то, скорее всего, ваши пакеты удалили код, который он действительно использует – casr

0

Я думаю, что нашел решение, которое работает достаточно хорошо. В качестве бонуса он не требует касания существующего кода (например, добавление проверки process.env.). Я написал преобразование браузера, которое, учитывая список модулей/файлов, заменяет их вызов 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; 

пакет.JSON конфигурация для преобразования

"browserify": { 
    "transform": [ 
     "babelify", 
     [ 
      "./derequire.js", 
      { 
       "modules": [ 
        "pica", 
        "exif-js", 
        "./src/thing.js", 
        "components/TextEditor.jsx", 
        "lib/FileUploader.js" 
       ] 
      } 
     ], 
     "browserify-css", 
     "imgurify", 
     "glslify" 
    ] 
}, 
Смежные вопросы