首页 > 解决方案 > Webpack 外部无法在父项目中解析

问题描述

我有一个库,这个库是 React 组件库,所以它依赖于reactreact-dom. 它还取决于react-router-dom(和传递react-router)。

这些是父项目提供的包。我不希望它们在捆绑包中。该库是使用 webpack 生成的,因此我已将它们添加到externals库 webpack 配置中的配置中,如下所示(Webpack v4.4)

const webpack = require("webpack");
const path = require("path");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");

module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, "dist"),
    libraryTarget: "commonjs",
  },
  externals: {
    "react-router": {
      "commonjs": "react-router",
      "commonjs2": "eact-router",
      "amd": "react-router",
      "root": "react-router"
    },
    "react-router-dom": {
      "commonjs": "react-router-dom",
      "commonjs2": "react-router-dom",
      "amd": "react-router-dom",
      "root": "react-router-dom"
    },
    "react": {
      "commonjs": "react",
      "commonjs2": "react",
      "amd": "react",
      "root": "React"
    },
    "react-dom": {
      "commonjs": "react-dom",
      "commonjs2": "react-dom",
      "amd": "react-dom",
      "root": "ReactDOM"
    }
  },
  // devtool: "cheap-eval-source-map",
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env", "@babel/preset-react"],
            plugins: [
              "@babel/plugin-transform-flow-strip-types",
              "@babel/plugin-proposal-object-rest-spread",
              "transform-class-properties",
            ],
          },
        },
      },
      {
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: [
            { loader: "css-loader", options: { minify: true } },
            "sass-loader",
          ],
        }),
      },
      {
        // Match woff2 in addition to patterns like .woff?v=1.1.1.
        test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          {
            loader: "url-loader",
            options: {
              // Limit at 50k. Above that it emits separate files
              limit: 50000,

              // url-loader sets mimetype if it's passed.
              // Without this it derives it from the file extension
              mimetype: "application/font-woff",

              // Output below fonts directory
              name: "./fonts/[name].[ext]",
            },
          },
        ],
      },
      {
        test: /\.svg$/,
        use: [
          {
            loader: "svg-inline-loader",
            options: {
              removeSVGTagAttrs: false,
            },
          },
        ],
      },
      {
        test: /\.(png|jp(e*)g)$/,  
        use: [{
            loader: 'url-loader',
            options: {
                limit: 8000, // Convert images < 8kb to base64 strings
                name: 'images/[hash]-[name].[ext]'
            }
        }]
    },
    ],
  },
  plugins: [
    new ExtractTextPlugin("styles.css"),
    new OptimizeCssAssetsPlugin({
      assetNameRegExp: /\.optimize\.css$/g,
      cssProcessor: require("cssnano"),
      cssProcessorOptions: { discardComments: { removeAll: true } },
      canPrint: true,
    }),
    new webpack.optimize.AggressiveMergingPlugin(),
  ],
};

但是,当我在父项目中包含库的输出时,它会在构建阶段抱怨

ERROR in ../moss/dist/bundle.js
Module not found: Error: Can't resolve 'react-router' in '/Users/ubermouse/code/moss/dist'
 @ ../moss/dist/bundle.js 19655:223-261
 @ ./matai/static_src/js/containers/App.js
 @ ./matai/static_src/js/containers/Root.js
 @ ./matai/static_src/js/index.js
 @ multi ./matai/static_src/js/utils/polyfills.js ./matai/static_src/js/index.js

我得到了 react-router 和 react-router-dom 的上述错误。我没有得到它的反应或反应域。

这里发生了什么?我使用外部错误吗?为什么它适用于 react/react-dom?他们只是还不需要吗?外部不能从父节点模块中提取依赖项吗?我已经为此扯了几个小时的头发了:(

我注意到一件事,react-router/react-router-dommodule在他们的 package.json 中有一个属性,所以他们的 ESModule 被加载了。react/react-router 没有。我不知道这是否会改变任何东西,但它确实

为了完整性,我们的父项目 webpack 配置

const webpack = require('webpack');
const path = require('path');
const config = require('./frontend.config');

/**
 * Base Webpack config, defining how our code should compile.
 */

module.exports = {
    entry: {
        vendor: [
            "moment",
            "react",
            "react-dom",
            "react-intl",
            "react-intl-redux",
            "react-redux",
            "react-leaflet",
            "react-router",
            "react-router-dom",
            "react-router-redux",
            "redux",
            "redux-observable",
            "rxjs",
        ],
        matai: [
            path.join(config.paths.js, 'utils', 'polyfills.js'),
            path.join(config.paths.js, 'index.js'),
        ],
    },

    output: {
        path: path.join(config.paths.build_js),
        filename: '[name].js',
    },

    plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            name: "vendor",

            minChunks: Infinity,
            // (with more entries, this ensures that no other module
            //  goes into the vendor chunk)
        }),
    ],

    module: {
        rules: [
            // Disable require.ensure as it's not a standard language feature.
            { parser: { requireEnsure: false } },

            // First, run the linter.
            // It's important to do this before Babel processes the JS.
            {
                test: /\.js$/,
                enforce: 'pre',
                use: ['eslint-loader'],
                include: path.join(config.paths.js),
            },
            {
                test: /\.js$/,
                use: ['babel-loader'],
                exclude: [/node_modules/],
            },
        ],
    },

    stats: {
        // Set the maximum number of modules to be shown
        maxModules: 3,
        // Add chunk information (setting this to `false` allows for a less verbose output)
        chunks: false,
        // Add the hash of the compilation
        hash: false,
        // `webpack --colors` equivalent
        colors: true,
        // Add information about the reasons why modules are included
        reasons: false,
        // Add webpack version information
        version: false,
    },

    // Some libraries import Node modules but don't use them in the browser.
    // Tell Webpack to provide empty mocks for them so importing them works.
    node: {
        fs: 'empty',
        net: 'empty',
        tls: 'empty',
    },
};

标签: javascriptwebpackreact-routerreact-router-dom

解决方案


推荐阅读