У меня есть динамически настраиваемая настройка веб-пакета с некоторыми пользовательскими загрузчиками. Каждому из этих загрузчиков нужен объект конфигурации, который известен только динамически, во время компиляции, поэтому его невозможно записать в options
загрузчика. Как загрузчики могут получить доступ к этому объекту? Есть ли "канонический" способ иметь глобальный компилятор в webpack?
В принципе, моя настройка позволяет использовать несколько динамических конфигураций времени сборки, она выглядит так:
// webpack.config.js
let defaults = {
....
module: {
loaders: [
{
test: '.some.special.stuff',
loader: 'my-own-loader',
}
}
module.exports = function main() {
let BUILD_CONFIG = require(process.env.BUILD_CONFIG);
....
return defaults;
}
Таким образом, веб-пакет должен быть вызван как BUILD_CONFIG=some-config.js webpack
. Обратите внимание, что some-config.js
содержит много материалов, не относящихся к веб-папке, поэтому я не могу просто вернуть его из main
или объединить с defaults
Теперь у меня есть my-own-loader
в my-own-loader.js
:
// my-own-loader.js
module.exports = function main(content) {
...
Мой вопрос заключается в том, как получить доступ к этой BUILD_CONFIG
переменной из WebPack main
в загрузчике main
.
Я думаю, что понимаю, что вы пытаетесь сделать, и иметь примерный проект, описывающий процесс.
Чтобы начать, я собираюсь установить переменную среды с именем TEST_VAR
через любой механизм, поддерживаемый моей платформой. Я нахожусь на macOS, чтобы export TEST_VAR=fizzbuzz
. Мой loader.js может использовать эту переменную среды через соглашение узла: process.env.TEST_VAR
.
Помните, что ваш webpack.config.js
по-прежнему является файлом JavaScript с запуском узла. Вы можете использовать все встроенные модули, поддерживающие этот узел, включая process.env
.
Рассмотрим следующие файлы и структуру:
webpack-test
|- package.json
|- webpack.config.js
|- index.html
|- /dist
|- bundle.js
|- /loaders
| obj-loader.js
|- /res
|- /obj
|- dummy.obj
|- /src
|- index.js
{
"name": "webpack-test",
"version": "0.0.1",
"main": "index.js",
"dependencies": {
"webpack": "^3.8.1"
},
"devDependencies": {
"http-server": "^0.10.0",
"loader-utils": "^1.1.0",
},
"scripts": {
"start": "http-server .",
"build": "webpack",
},
}
const path = require("path");
module.exports = {
entry: "./src/index.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist")
},
resolveLoader: {
modules: [
path.resolve(__dirname, "loaders")
]
},
module: {
rules: [
{
test: /\.obj$/,
use: {
loader: "obj-loader",
options: {
dummyText: "lorem ipsum"
}
}
}
]
}
};
const loaderUtils = require("loader-utils"),
schemaUtils = require("schema-utils");
function loader(source) {
const options = loaderUtils.getOptions(this);
console.log(options);
let tmp = process.env.TEST_VAR;
if (tmp === undefined) {
console.warn("TEST_VAR is not defined");
}
return 'export default function(){return "TEST_VAR: ${tmp} || ${source} || ${options.dummyText}";}';
}
module.exports = loader;
Hello
import dummy from "../res/obj/dummy.obj";
(function () {
"use strict";
function main() {
document.querySelector("p").innerHTML = dummy();
}
document.addEventListener("DOMContentLoaded", main);
}());
<!DOCTYPE html>
<html lang="en">
<head>
<title>Webpack Test</title>
<script src="dist/bundle.js"></script>
</head>
<bod>
<main>
<h1>Webpack Test</h1>
<p>Lorem Ipsum</p>
</main>
</bod>
</html>
Всякий раз, когда я создаю и запускаю эту веб-страницу, я получаю то, что составляет:
<main>
<h1>Webpack Test</h1>
<p>TEST_VAR: fizzbuzz || Hello || lorem ipsum</p>
</main>
Где "fizzbuzz" было добавлено из переменной среды "Hello", источник находится в /res/obj/dummy.obj
, а "lorem ipsum" - это текст, который я указал как параметр dummyText
для obj-loader
. Однако он мог бы так же легко получить переменную окружения, которую я установил.
Дополнительное обновление на основе редактирования
Учитывая ваше редактирование, что с этим делать; вместо того, чтобы устанавливать правило по defaults
установите его в экспортируемой функции, чтобы получить доступ к области. Затем добавьте правила загрузчика на основе нового синтаксиса правила: module.loaders
теперь module.rules
. Таким образом, у вас есть доступ к options
в вашем пользовательском загрузчике и, следовательно, у вас есть доступ к BUILD_CONFIG
.
// Hypothetically you run:
// export BUILD_CONFIG=some-config.js
// Which sets:
// process.env.BUILD_CONFIG = "some-config.js";
// New Webpack loader/rules syntax
// https://webpack.js.org/guides/migrating/#module-loaders-is-now-module-rules
let defaults = {
module: {
rules: [
/*
*Set this later in exported function
{
test: ".some.special.stuff",
use: {
loader: "my-own-loader",
options: {
some: "options"
}
}
}
*/
]
}
};
module.exports = function (content) {
let BUILD_CONFIG = require(process.env.BUILD_CONFIG);
// Other code
let dd = defaults;
defaults.module.rules.push({
test: ".some.special.stuff",
use: {
loader: "my-own-loader",
options: {
stuffFromEnvConfig: BUILD_CONFIG
}
}
});
return dd;
};
const loaderUtils = require("loader-utils"),
schemaUtils = require("schema-utils");
module.exports = function main(content) {
const options = loaderUtils.getOptions(this);
console.log(options);
let tmp;
if (options.stuffFromEnvConfig.useFirst) {
tmp = "Fizz";
} else {
tmp = "Buzz";
}
return 'export default function(){return "TEST_VAR: ${tmp}";}';
};
process.env
.