webpack:在同一个模块中使用import和module.exports导致错误

79

我正在使用Webpack开发一个网站。当代码如下时:

// code example
import $ from 'jquery';
function foo() {};
module.exports = foo;

我遇到了错误 Uncaught TypeError: Cannot assign to read only property 'exports' of object '#<Object>'

事实证明将import $ from 'jquery'更改为var $ = require('jquery')不会引起任何错误。

为什么使用module.exports导入会导致这个错误?使用require有什么问题吗?


@MatthewHerbst 修改了主要问题。 - llanfair
JS 应该只保留 require,不应该引入其他的方式。现在有两种不兼容的方式,导致混乱不堪。有些需要使用 require,而另一些则需要使用 import,同时你的 babel 设置也会产生影响。 - sudo
4个回答

134

不能混合使用 importmodule.exports。在 import 的世界中,你需要导出东西。

// Change this
module.exports = foo;

// To this
export default foo;

2
更多关于此内容的信息(以及如何导出多个函数或对象):https://24ways.org/2014/javascript-modules-the-es6-way/ - jean d'arme
尝试一下这个非常有用的链接。 - Yohan W. Dunon
这不适用于 modele.exports = { foo: function () {} } - dǝɥɔS ʇoıןןƎ

81

如果下游的其他模块具有意外的 require 树,就会发生这种情况。Babel 会将不应该被转换为 import 的 require 改为 import,从而导致上述问题(@Matthew Herbst)。要解决此问题,请在您的 babelrc 文件或 babel.config.js 中添加 "sourceType": "unambiguous",以便 @babel/plugin-transform-runtime 不会对 commonjs 文件中的 require 表达式进行更改。例如:

module.exports = {
  presets: [
    '@quasar/babel-preset-app'
  ],

  "sourceType": "unambiguous"
}

谢谢。虽然这是现代浏览器的好解决方案,但它无法在IE11或以下版本上加载。 - Bitfinicon
2
希望这个答案能被采纳,而不是那个要求删除module.exports的答案,因为将CommonJS模块转换为ES6并不总是可行的选择。感谢您提供的解决方案! - sgarcia.dev

4
你可以在导出语句中使用 require,但不能使用 import 和 module.exports。

1

在我的react-native-web案例中,只需使用一个额外的webpack规则,就可以解决TypeError: Cannot assign to read only property 'exports' of object的问题。也许你可以参考一下。

npm install --save-dev react-app-rewired

在您的项目根目录中创建一个 config-overrides.js 文件。
// used by react-app-rewired

const webpack = require('webpack');
const path = require('path');

module.exports = {
  webpack: function (config, env) {
    config.module.rules[1].use[0].options.baseConfig.extends = [
      path.resolve('.eslintrc.js'),
    ];

    // To let alias like 'react-native/Libraries/Components/StaticRenderer'
    // take effect, must set it before alias 'react-native'
    delete config.resolve.alias['react-native'];
    config.resolve.alias['react-native/Libraries/Components/StaticRenderer'] =
      'react-native-web/dist/vendor/react-native/StaticRenderer';
    config.resolve.alias['react-native'] = path.resolve(
      'web/aliases/react-native',
    );

    // Let's force our code to bundle using the same bundler react native does.
    config.plugins.push(
      new webpack.DefinePlugin({
        __DEV__: env === 'development',
      }),
    );

    // Need this rule to prevent `Attempted import error: 'SOME' is not exported from` when `react-app-rewired build`
    // Need this rule to prevent `TypeError: Cannot assign to read only property 'exports' of object` when `react-app-rewired start`
    config.module.rules.push({
      test: /\.(js|tsx?)$/,
      // You can exclude the exclude property if you don't want to keep adding individual node_modules
      // just keep an eye on how it effects your build times, for this example it's negligible
      // exclude: /node_modules[/\\](?!@react-navigation|react-native-gesture-handler|react-native-screens)/,
      use: {
        loader: 'babel-loader',
      },
    });

    return config;
  },
  paths: function (paths, env) {
    paths.appIndexJs = path.resolve('index.web.js');
    paths.appSrc = path.resolve('.');
    paths.moduleFileExtensions.push('ios.js');
    return paths;
  },
};

同时创建一个web/aliases/react-native/index.js文件。
// ref to https://levelup.gitconnected.com/react-native-typescript-and-react-native-web-an-arduous-but-rewarding-journey-8f46090ca56b

import {Text as RNText, Image as RNImage} from 'react-native-web';
// Let's export everything from react-native-web
export * from 'react-native-web';

// And let's stub out everything that's missing!
export const ViewPropTypes = {
  style: () => {},
};
RNText.propTypes = {
  style: () => {},
};
RNImage.propTypes = {
  style: () => {},
  source: () => {},
};

export const Text = RNText;
export const Image = RNImage;
// export const ToolbarAndroid = {};
export const requireNativeComponent = () => {};

现在你只需要运行react-app-rewired start而不是react-scripts start

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接