【问题标题】:Webpack DllPlugin with gulp: Cannot find module '... vendor-manifest.json'带有 gulp 的 Webpack DllPlugin:找不到模块'... vendor-manifest.json'
【发布时间】:2017-08-01 13:01:24
【问题描述】:

我有一个使用 webpack 2 构建的相当大的 React 应用程序。该应用程序作为现有站点中的 SPA 嵌入到 Drupal 站点中。 Drupal 站点有一个复杂的 gulp 构建设置,我无法使用 webpack 复制它,所以我决定保留它。

我使用 DllPlugin / DllReferencePlugin 组合将我的 React 应用程序拆分为多个部分,该组合在 webpack 2 中开箱即用。这很好用,并且在使用 webpack 构建时我得到了一个不错的供应商捆绑包。

问题是当我尝试在 gulp 中运行我的 webpack 配置时,我得到一个错误。我可能做错了,因为我无法找到关于这种方法的太多文档,但是,它对我不起作用。

它看起来像是在创建之前尝试从我的供应商捆绑包中包含清单文件。

每当我运行我定义的 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-bundle 并创建vendor-manifest.json 文件,那么我随后可以成功运行我的gulp 任务而没有任何问题。

虽然这不是很有帮助,因为这仍然不允许我将 webpack 与 gulp 一起使用,因为我打算在新构建运行之前清理构建。

【问题讨论】:

    标签: javascript gulp webpack-2 build-tools


    【解决方案1】:

    我最终使用了问题末尾提到的解决方案。我先构建我的 DLL 文件,然后我可以成功运行我的 gulp webpack 任务。

    可以更轻松地调试问题的一项更改是使用 Gulp 实用程序模块 (gulp-util) 显示在使用 gulp 构建 webpack 期间可能出现的任何 webpack 错误。

    我最终的 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');
    });
    

    我希望这可能对处于类似情况的人有所帮助。

    【讨论】:

      【解决方案2】:

      每当我运行我定义的 gulp 任务之一时,例如 gulp react-vendor,我都会收到一个错误,说它无法解析 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 中的代码,从那里它会看到在您创建 DllReferencePlugin 时使用的require(),因此它也会尝试在那时读取manifest.json 并将其转换为对象...在它被构建之前。

      您可以通过以下两种方式之一解决此问题:

      1. DllReferencePlugin 的manifest 选项支持一个对象(这是您当前提供的),或者一个包含清单文件路径的字符串。换句话说,如果您从您的 path.join(...) 呼叫周围删除 require(),它应该可以工作。
      2. 或者,您也可以延迟加载 Webpack 配置文件。将您的 const reactConfig = require('./webpack.config.js'); 从文件顶部直接移动到 gulp 任务函数中就足够了,假设在构建清单之后才调用此函数。

      【讨论】:

        猜你喜欢
        • 2016-01-20
        • 1970-01-01
        • 2017-06-24
        • 2019-05-26
        • 2017-01-03
        • 2015-11-10
        • 1970-01-01
        • 2017-03-02
        • 2016-06-19
        相关资源
        最近更新 更多