Я пытаюсь настроить загрузку файлов .pug
с помощью Webpack в зависимости от временного расширения имени файла, при этом оно должно быть по умолчанию. В моем случае файлы, имена которых заканчиваются на .vue.pug
, должны быть загружены по другим правилам, чем простые .pug
.
В приведенной выше настройке часть { test: /\.vue.pug$/, /* ... */ }
связана с фреймворком Vue, и мне порекомендовали разработчики @webdiscus/pug-loader. Последняя часть (test: /(?!.*\.vue\.pug$).*\.pug$/
) — это загрузчик по умолчанию для файлов Pug.
{
// ...
module: {
//
rules: [
// === Loading of Pug from files related with Vue
{
test: /\.vue.pug$/,
oneOf: [
// allow <template lang = "pug"> in Vue components
{
resourceQuery: /.vue$/u,
loader: '@webdiscus/pug-loader', // <-- it is same pug-loader as in PugPlugin.loader
options: {
method: 'html', // render Pug into pure HTML string
},
},
// allow import of Pug in JS/TS and for "other cases", if a file hasn't the extension `.vue`
{
resourceQuery: ".vue.ts",
loader: '@webdiscus/pug-loader', // <-- it is same pug-loader as in PugPlugin.loader
options: {
method: 'compile', // compile Pug into template function, use it if you want pass custom data into template on clinet-side rendering.
//method: 'render', // compile Pug into template string, use if your template has't external custom data, generates smallest file
//esModule: true, // should be `true` for importing in ES module, e.g. `import tmpl from './myTemplate.pug';`
// defaults is false, used for CommonJS, e.g. `const tmpl = require('./myTemplate.pug');`
// NOTE: this option is optional, if it is not defined, importing in ES module works too.
},
},
],
},
// Loading of Pug from files not related with Vue
{
test: /(?!.*\.vue\.pug$).*\.pug$/,
loader: '@webdiscus/pug-loader',
options: {
method: 'render'
},
},
]
},
// ...
};
Хотя постройка выполняется без ошибок, если запустить скрипт в браузере, то получим ошибку:
Uncaught TypeError: _ExampleMultipleFilesComponent_vue_pug__WEBPACK_IMPORTED_MODULE_0___default(...) is not a function
Если удалить часть ниже и не импортировать файлы .pug
в файлы, отличные от vue, ошибки не будет.
{
test: /(?!.*\.vue\.pug$).*\.pug$/,
loader: '@webdiscus/pug-loader',
options: {
method: 'render'
},
}
Похоже я не понимаю, как Webpack выбирает подходящий загрузчик. Пожалуйста, объясни.
Репозиторий репродукций (убедитесь, что вы проверяете ветку @problem/default_loader)
@morganney, спасибо за ссылку. В упомянутом вами ответе оба загрузчика будут активированы. Но что, если требуется только один из них?
Хотя постройка выполняется без ошибок, если запустить скрипт в браузере, то получим ошибку:
Я не могу воспроизвести ошибку в браузере (FireFox). В браузере я вижу скомпилированные компоненты Vue:
Example single file component
Example multiple files component with custom variable "someText": Hello Pug!
{
test: /\.pug$/,
oneOf: [
// [1] issuer is VUE file
{
resourceQuery: /^\?vue/u,
loader: '@webdiscus/pug-loader',
options: {
method: 'html', // exports rendered HTML sting
},
},
// [2] issuer is TS file
{
loader: '@webdiscus/pug-loader',
options: {
method: 'compile', // export compiled template function
},
},
],
}
Вы загружаете куда угодно файл Pug .pug
, затем Webpack выбирает правило для обработки этого файла через загрузчик.
Важно, где загружается файл Pug, поскольку для каждого issuer
(родителя) будет генерироваться ожидаемый результат.
У вас есть два типа эмитентов:
Vue
файл.
Если вы используете код Pug в файле Vue, например. в ExampleSingleFileComponent.vue
, затем в Webpack выберите загрузчик [1]
с параметрами рендеринга Pug в чистую строку HTML
, как и ожидается в данном случае.
TS
файл.
Если вы загружаете файл Pug в TS/JS, например. в ExampleMultipleFilesComponent.vue.ts
затем в Webpack выберите [2]
загрузчик с параметрами для компиляции файла Pug в JS template function
. Эту функцию шаблона вы можете вызвать с переменными, чтобы преобразовать ее в HTML во время выполнения в браузере.
пожалуйста, обновите версию с @webdiscus/pug-loader
на 2.11.0
Спасибо за ответ и комментарий. Я обновил репозиторий репродукций, включая обновление зависимостей. Теперь вы получите сообщение об ошибке в своем браузере. Что касается предустановки Webpack, в моем случае я установил `test: /\.vue.pug$/,, not
test: /\.pug$/, so it must be applied only for files ends with
.vue.pug. But for some reason, the loader with
test: /(?!.*\.vue \.pug$).*\.pug$/` загружает ExampleMultipleFilesComponent.vue.pug
. Ошибка в регулярном выражении?
Я готов дать приз репутации за объяснение, которое решит эту проблему. Надеюсь, это будет ваш. Если вы будете так любезны и просмотрите репозиторий репродукций, убедитесь, что вы извлекли ветку @problem/default_loader.
@TakeshiTokugawaYD Я создал пиар в твоей ветке. Пожалуйста, прочитайте мои комментарии в коде. Вкратце: ваша конфигурация веб-пакета была неправильной ;-)
Спасибо за пул реквест! Я проверил ваши комментарии, и теперь воспроизведение работает нормально. Но почему я спросил: «Какой порядок...?» Мне нужно интегрировать специальный загрузчик Pug, который загружает Pug AST для файлов с определенным временным расширением имени файла (например, «**.myext.pug»). Ваш пресет довольно прост и понятен, но я полагаю, что для решения моей проблемы мне нужно его глубоко изменить. Именно поэтому я попробовал { test: /(?!.*\.vue\.pug$).*\.pug$/ }
. Извините, но чтобы решить этот вопрос, мне нужно понять, как загружать файлы с определенным расширением с помощью определенных загрузчиков.
Я объединил ваш запрос на включение, и теперь в ветке master
есть новейший код. Также я добавил PugAST_Loader
в проект. Пожалуйста, подскажите мне, как применить этот загрузчик только для файлов pug с определенным временным расширением имени файла (например, «**.myext.pug»).
нет-нет, ваш PugAST_Loader.ts не будет работать. Какова цель вашего загрузчика AST? Что это делает? Какой результат возвращается?
Любой загрузчик веб-пакета будет вызываться, когда правило загрузчика соответствует требуемому/импортированному файлу или файлу из записи. Но в вашей основной ветке PugAST_Loader нигде не используется. Сделайте, пожалуйста, ветку с примером с вашим вариантом использования в исходном коде и с ожидаемым результатом.
@TakeshiTokugawaYD, обычно вместо { test: /(?!.*\.vue\.pug$).*\.pug$/ }
следует использовать правильную конфигурацию: { test: /\.pug$/, exclude: /\.vue\.pug$/ }
ОК, спасибо за помощь! Я принял и проголосовал за ваш ответ.
На ваш вопрос, загрузчики в Webpack выполняются снизу вверх по массиву конфигурации. Например, для массива загрузчиков [1, 2, 3, 4, 5]
порядок выполнения будет 5->4->3->2-> 1
. Каждый загрузчик обрабатывает модуль, а затем передает преобразованный модуль следующему загрузчику в последовательности, позволяя нескольким загрузчикам изменять код.
В конфигурации вашего Webpack вы используете функцию oneOf
. Это позволяет вам настроить список загрузчиков, которые применяются только на основе определенных условий, таких как resourceQuery
. Когда загрузчик верхнего уровня, например, для файлов .pug
, находит совпадение, Webpack затем проверяет список oneOf
. В отличие от основной конфигурации, где загрузчики работают снизу вверх, oneOf
проверяет сверху вниз. Используется только первый загрузчик, соответствующий списку oneOf
, и после этого он перестает следить за ним. Таким образом, изменения, внесенные этим загрузчиком, не передаются другим загрузчикам в списке oneOf.
Они загружаются снизу вверх, и ответ на этот вопрос дан здесь: stackoverflow.com/a/32234468/258174, а также в их документации. Я не понимаю, почему нельзя просто определить два правила с помощью
test: /\.vue\.pug$/
иtest: /\.pug$/
, а затем использоватьinclude
илиexclude
соответственно?