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;
некоторый футуристический оптимизатор действительно обрабатывает такую ситуацию. расфасовывать будет оценивать код во время компиляции и вычисленные выходные значения. Однако, как правило, производство не считается готовым.