Webpack: как конвертировать переменные при построении
о Vue (vue-loader) + Webpack и хроматизм
пример: (на dev / source)
let textColor = chromatism.contrastRatio('#ffea00').cssrgb // => rgb(0,0,0)
можно ли сказать Webpack для преобразования to rgb(0,0,0) on строить версии?
на строить версии должно быть преобразовано что-то вроде: (for производительность)
let textColor = 'rgb(0,0,0)'
3 ответов
как уже упоминалось в предыдущих ответах и комментариях, нет доступных компиляторов AOT для обработки такой ситуации (я имею в виду, что это очень конкретный случай, и никакой инструмент общего назначения не может справиться с этим), ничто не мешает вам развернуть свой собственный загрузчик/плагин для обработки этой задачи!
Вы можете использовать пользовательский Загрузчик Webpack и модуль виртуальной машины узла чтобы выполнить код в buildtime, получите его вывод и замените его с вызовом функции в исходном файле.
Пример реализации этой идеи может выглядеть следующим образом:
// file: chromatismOptimizer.js
// node's vm module https://nodejs.org/api/vm.html
const vm = require('vm')
const chromatism = require('chromatism')
// a basic and largley incomplete regex to extract lines where chromatism is called
let regex = /^(.*)(chromatism\S*)(.*)$/
// create a Sandbox
//https://nodejs.org/api/vm.html#vm_what_does_it_mean_to_contextify_an_object
// this is roughly equivalent to the global the context the script will execute in
let sandbox = {
chromatism: chromatism
}
// now create an execution context for the script
let context = new vm.createContext(sandbox)
// export a webpack sync loader function
module.exports = function chromatismOptimizer(source){
let compiled = source.split('\n').reduce((agg, line) => {
let parsed = line.replace(regex, (ig, x, source, z) => {
// parse and execute the script inside the context
// return value is the result of execution
// https://nodejs.org/api/vm.html#vm_script_runincontext_contextifiedsandbox_options
let res = (new (vm.Script)(source)).runInContext(context)
return `${x}'${res}'${z? z : ''}`
})
agg.push(parsed)
return agg;
}, []).join('\n');
return compiled;
}
затем в производства.webpack.js (или что-то вроде этого) взято из этот вопрос:
// Webpack config
resolveLoader: {
alias: {
'chromatism-optimizer': path.join(__dirname, './scripts/chromatism-optimizer'),
},
}
// In module.rules
{
test: /\.js$/,
use: ['chromatism-optimizer'],
}
Примечание: это просто эталонная реализация и в значительной степени неполной. Регулярное выражение, используемое здесь, довольно простое и может не охватывать многие другие случаи использования, поэтому убедитесь, что вы обновили регулярное выражение. Также весь этот материал может быть реализован с помощью плагинов webpack (просто у меня недостаточно знаний о том, как его создать). Для быстрого стартера обратитесь к этой wiki чтобы узнать, как создать пользовательский плагин.
основная идея проста.
сначала создайте изолированную среду,
let sandbox = { chromatism:chromatism, ...}затем создайте выполнение контекст,
let context = new vm.createContext(sandbox)затем для каждого допустимого источника выполните инструкцию source в контексте и получите результат.
let result = (new (vm.Source)(source)).runInContext(context)затем, возможно, замените исходный исходный оператор на результат.
попробуйте использовать обратный звонок loader для обработки всего вашего JavaScript. Определите функцию обратного вызова для этого конкретного случая или даже что-то более общее, например:
evalDuringCompile: function(code) { return JSON.stringify(eval(code)); }
современный оптимизатор не может обрабатывать произвольное выражение. В этом случае наиболее надежным решением является константа жесткого кода в вашем коде.
let textColor = process.env.NODE_ENV === 'production' ? 'rgb(0,0,0)' : chromatism.contrastRatio('#ffea00').cssrgb;
некоторый футуристический оптимизатор действительно обрабатывает такую ситуацию. расфасовывать будет оценивать код во время компиляции и вычисленные выходные значения. Однако, как правило, производство не считается готовым.