Webpack DllPlugin с gulp: не удается найти модуль '... vendor-manifest.json'
У меня довольно большое приложение React, созданное с помощью веб-пакета 2. Приложение встроено в сайт Drupal в качестве SPA на существующем сайте. Сайт Drupal имеет сложную настройку сборки gulp, и я не могу скопировать его с веб-пакетом, поэтому я решил оставить его.
Я разделил свое приложение React на несколько частей, используя комбо DllPlugin / DllReferencePlugin, которое поставляется из коробки в веб-пакете 2. Это прекрасно работает, и я получаю хороший пакет поставщиков при сборке с веб-пакетом.
Проблема в том, что когда я пытаюсь запустить конфигурацию моего веб-пакета в gulp, я получаю сообщение об ошибке. Возможно, я делаю это неправильно, так как мне не удалось найти много документации по этому подходу, но, тем не менее, он не работает для меня.
Похоже, что он пытается включить файл манифеста из моего комплекта поставщика до его создания.
Всякий раз, когда я запускаю одну из моих определенных задач, например gulp react-vendor
Я получаю сообщение об ошибке, в котором говорится, что он не может разрешить файл vendor-manifest.json.
Если я с другой стороны бегу webpack --config=webpack.dll.js
в моем терминале webpack компилируется просто отлично и без ошибок.
Я включил то, что я считаю соответствующими файлами. Любая помощь по этому вопросу приветствуется.
webpack.config.js
// Use node.js built-in path module to avoid path issues across platforms.
const path = require('path');
const webpack = require('webpack');
// Set environment variable.
const production = process.env.NODE_ENV === "production";
const appSource = path.join(__dirname, 'react/src/');
const buildPath = path.join(__dirname, 'react/build/');
const ReactConfig = {
entry: [
'./react/src/index.jsx'
],
output: {
path: buildPath,
publicPath: buildPath,
filename: 'app.js'
},
module: {
rules: [
{
exclude: /(node_modules)/,
use: {
loader: "babel-loader?cacheDirectory=true",
options: {
presets: ["react", "es2015", "stage-0"]
},
},
},
],
},
resolve: {
modules: [
path.join(__dirname, 'node_modules'),
'./react/src/'
],
extensions: ['.js', '.jsx', '.es6'],
},
context: __dirname,
devServer: {
historyApiFallback: true,
contentBase: appSource
},
// TODO: Split plugins based on prod and dev builds.
plugins: [
new webpack.DllReferencePlugin({
context: path.join(__dirname, "react", "src"),
manifest: require(path.join(__dirname, "react", "vendors", "vendor-manifest.json"))
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
filename: 'webpack-loader.js'
}),
]
};
// Add environment specific configuration.
if (production) {
ReactConfig.plugins.push(
new webpack.optimize.UglifyJsPlugin()
);
}
module.exports = [ReactConfig];
webpack.dll.js
const path = require("path");
const webpack = require("webpack");
const production = process.env.NODE_ENV === "production";
const DllConfig = {
entry: {
vendor: [path.join(__dirname, "react", "vendors", "vendors.js")]
},
output: {
path: path.join(__dirname, "react", "vendors"),
filename: "dll.[name].js",
library: "[name]"
},
plugins: [
new webpack.DllPlugin({
path: path.join(__dirname, "react", "vendors", "[name]-manifest.json"),
name: "[name]",
context: path.resolve(__dirname, "react", "src")
}),
// Resolve warning message related to the 'fetch' node_module.
new webpack.IgnorePlugin(/\/iconv-loader$/),
],
resolve: {
modules: [
path.join(__dirname, 'node_modules'),
],
extensions: ['.js', '.jsx', '.es6'],
},
// Added to resolve a dependency issue in this build #https://github.com/hapijs/joi/issues/665
node: {
net: 'empty',
tls: 'empty',
dns: 'empty'
}
};
if (production) {
DllConfig.plugins.push(
new webpack.optimize.UglifyJsPlugin()
);
}
module.exports = [DllConfig];
vendors.js (чтобы определить, что добавить в Dll)
require("react");
require("react-bootstrap");
require("react-dom");
require("react-redux");
require("react-router-dom");
require("redux");
require("redux-form");
require("redux-promise");
require("redux-thunk");
require("classnames");
require("whatwg-fetch");
require("fetch");
require("prop-types");
require("url");
require("validator");
gulpfile.js
'use strict';
const gulp = require('gulp');
const webpack = require ('webpack');
const reactConfig = require('./webpack.config.js');
const vendorConfig = require('./webpack.dll.js');
// React webpack source build.
gulp.task('react-src', function (callback) {
webpack(reactConfig, function (err, stats) {
callback();
})
});
// React webpack vendor build.
gulp.task('react-vendor', function (callback) {
webpack(vendorConfig, function (err, stats) {
callback();
})
});
// Full webpack react build.
gulp.task('react-full', ['react-vendor', 'react-src']);
ПРИМЕЧАНИЕ: если я соберу свой вендор-пакет с терминалом с webpack --config=webpack.dll.js
сначала он создает файл vendor-manifest.json, а затем я могу успешно выполнить свои задачи без проблем.
Это не очень полезно, так как это все еще не позволит мне использовать webpack с gulp, так как я собираюсь очистить сборку перед запуском новых сборок.
2 ответа
Я закончил тем, что использовал решение, упомянутое в конце моего вопроса. Сначала я создаю свой DLL-файл, а затем могу успешно запускать задачи gulp webpack.
Одним из изменений, которое может облегчить отладку проблемы, является использование служебного модуля Gulp ( gulp-util) для отображения любых ошибок веб-пакета, которые могут появиться во время сборки веб-пакета с использованием gulp.
Моя окончательная настройка глотка в конечном итоге выглядела так:
gulpfile.js
'use strict';
const gulp = require('gulp');
const gutil = require('gulp-util');
const webpack = require('webpack');
const reactConfig = require('./webpack.config.js');
const vendorConfig = require('./webpack.dll.js');
// React webpack source build.
gulp.task('react', function (callback) {
webpack(reactConfig, function (err, stats) {
if (err) {
throw new gutil.PluginError('webpack', err);
}
else {
gutil.log('[webpack]', stats.toString());
}
callback();
});
});
// React webpack vendor build.
gulp.task('react-vendor', function (callback) {
webpack(vendorConfig, function (err, stats) {
if (err) {
throw new gutil.PluginError('webpack', err);
}
else {
gutil.log('[webpack]', stats.toString());
}
callback();
});
});
// React: Rebuilds both source and vendor in the right order.
gulp.task('react-full', ['react-vendor'], function () {
gulp.start('react');
});
Я надеюсь, что это может помочь кому-то в подобной ситуации.
Всякий раз, когда я запускаю одну из моих определенных задач gulp, например gulp реагировать-вендор, я получаю сообщение об ошибке, в котором говорится, что он не может разрешить файл vendor-manifest.json.
Ваш gulpfile.js содержит это:
const reactConfig = require('./webpack.config.js');
const vendorConfig = require('./webpack.dll.js');
И webpack.config.js содержит это:
new webpack.DllReferencePlugin({
context: path.join(__dirname, "react", "src"),
manifest: require(path.join(__dirname, "react", "vendors", "vendor-manifest.json"))
}),
require()
вызовы в настоящее время все выполняются немедленно. Каждый раз, когда вы запускаете Gulp, он оценивает оба файла конфигурации Webpack. Как в настоящее время настроено, Node запускает код в webpack.config.js
при запуске, и оттуда он видит require()
используется при создании DllReferencePlugin, поэтому он также попытается прочитать manifest.json
в это время и превратить его в объект... который до того, как он был построен.
Вы можете решить это одним из двух способов:
- DllReferencePlugin's
manifest
Параметр поддерживает либо объект (который вы сейчас предоставляете), либо строку, содержащую путь к файлу манифеста. Другими словами, это должно работать, если вы удалитеrequire()
со всего вашегоpath.join(...)
вызов. - Кроме того, вы также можете отложить загрузку файлов конфигурации Webpack. Перемещение вашего
const reactConfig = require('./webpack.config.js');
из верхней части файла непосредственно в функцию задачи gulp должно быть достаточно, при условии, что эта функция не вызывается до тех пор, пока не будет создан манифест.