添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account Cannot assign to read only property 'exports' of object '#<Object>' (mix require and export) #4039 Cannot assign to read only property 'exports' of object '#<Object>' (mix require and export) #4039 DimitryDushkin opened this issue Jan 19, 2017 · 113 comments
Cannot assign to read only property 'exports' of object '#<Object>'

Appeared after upgrade webpack 2.2.0.rc.6 -> 2.2.0.

If 'harmony-module' is ES2015 module, then looks like it's now impossible to mix require and export default in single module. If it so, that's okay, but should be mentioned in docs.

Please mention other relevant information such as the browser version, Node.js version, webpack version and Operating System.
MacOS 10.12.2
node.js 6.9.2
webpack 2.2

a-x-, vinnymac, adamcrown, majioa, wisetc, kaosat-dev, yvele, MrSuperJ, zolotykh, JacopKane, and 102 more reacted with thumbs up emoji wisetc, PrestonII, malaypeaas, rovshenn, zilong-thu, ZelCloud, laneschmidt, and tpikachu reacted with hooray emoji oude3c reacted with heart emoji All reactions Cannot assign to read only property 'exports' of object '#<Object>' Cannot assign to read only property 'exports' of object '#<Object>' (mix require and export) Jan 19, 2017 francoisromain, ktquez, MrCuriosity, hzuhyb, Orhideous, wuchangming, sandiprb, Kamilius, manjitkumar, teledirigido, and 559 more reacted with thumbs up emoji shreyasparbat, shivam-perpetualny, jalasem, taroyamashita, mithom, jatd, ruanmer, gao-cq, vipulpant1989-zz, s-pace, and 12 more reacted with thumbs down emoji percy507, Nunchakus888, ohxyz, TongDaDa, sidthekidder, webermori, whoisjorge, ZaidRehman, eyexx, ioanlucut, and 41 more reacted with laugh emoji Beatt, JackJackNg, Cethy, webermori, mxschumacher, eyexx, anton-bot, ioanlucut, skjnldsv, jintangWang, and 45 more reacted with hooray emoji code-for-coffee, yazeedb, Donny5300, farskid, imtiyazs, elquimista, TongDaDa, Beatt, nitkuk, leovandriel, and 96 more reacted with heart emoji quocle108, chevalam, Sjhb, useafterfree, thelastinuit, derNoaa, shivam-perpetualny, cawfree, huguie, Knove, and 26 more reacted with rocket emoji phpjungle, quocle108, eponesh, useafterfree, thelastinuit, king-love-tech, gluons, shivam-perpetualny, cawfree, jalasem, and 32 more reacted with eyes emoji All reactions

@sokra probably in real code I had something more, that caused the issue. Now I've refactored this part to import export and it works fine.

I'll try check it in more clear example. For now I believe the issue can be closed.

This issue was newly affecting me after instructing Babel to not transpile module syntax. As sokra described, it only occurred when trying to use CommonJS style module.exports inside of ES modules. require always works. This can be fixed by simply replacing all module.exports = ... to export default ... where applicable, as this is seemingly equivalent for old Babel-style ES module transpilation. (Note though, that importing this module using require will probably give you an option with a default key rather than the default export itself, so it's probably best you make the switch across the entire codebase at once.)

ndabAP, tiendq, lazybios, johnmerced-ks, fabiotatsuo, msrxse, sg552, hileix, mpacary, Felwin, and 54 more reacted with thumbs up emoji sbefort, longtraneh, tbence94, and IrfDev reacted with thumbs down emoji JonathanPorta, kaline, Rigidoont, and TheBoroer reacted with hooray emoji xoen, sergey-suslov, mpacary, WaSheep, JBradBarnes, Jwalin-Thaker, sbefort, Pioneer101, and Gribbs reacted with confused emoji sbefort, CerineBnsd, and isuyashpatel reacted with eyes emoji All reactions

I find myself also being bitten by this issue since upgrading to 2.2.0. In my case, my hypothesis is a require chain that looks like:

CommonJSModule --requires--> ESModule --requires--> AnotherCommonJSModule

I'm sorry that I can't provide any more details at this time.

I'm not at all familiar with the internals but a quick, manual binary search suggests the regression is here: v2.2.0-rc.4...v2.2.0-rc.5

Attn: @sokra, @TheLarkInn I think this issue should be re-opened.

Taking a quick glance, this is definitely the culprit:

a7a4184

detect harmony modules before parsing
exports is now undefined in ESM
module.exports is now read-only in ESM and returns undefined
define is now undefined in ESM

As it says, module.exports is read-only in ES modules. If you're getting module.exports as read-only in a CommonJS module, THAT would be a bug, but that file is very much not a CommonJS file if it contains any export/import statements. I can confirm that this was the problem in my case and it was fixed by making my ES modules properly use ES exports. As a note require still works just fine inside of any module.

From my PoV it seems like Webpack's new behavior ultimately makes a lot more sense than the old behavior. It is fairly inane to allow mixing of import statements and CommonJS module.exports, and probably was never intended to work that way.

SergeAx, kohlmannj, cycold, hackape, francois-codes, cguillemette, happier2, kenberkeley, dannyrb, oude3c, and 14 more reacted with thumbs up emoji cguillemette, kenberkeley, givanse, Herz3h, and xkr47 reacted with heart emoji All reactions "plugins": ["transform-runtime", "syntax-dynamic-import"]

webpack.config.js (simplified):

'use strict';
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const Path = require('path');
const Webpack = require('webpack');
const config = {
    cache: true,
    devtool: process.env.NODE_ENV !== 'production' ? 'source-map' : false,
    context: Path.join(__dirname),
    output: {
        path: Path.join(__dirname, 'build'),
        filename: '[name].js',
        chunkFilename: '[name].js',
        publicPath: '/static/',
    recordsPath: Path.join(__dirname, 'recordsCache'),
    module: {
        rules: [{
                test: /\js$/,
                exclude: /node_modules/,
                use: [
                        loader: 'ng-annotate-loader',
                        loader: 'babel-loader',
                        options: {
                            cacheDirectory: true,
                        loader: 'string-replace-loader',
                        options: {
                            multiple: [
                                { search: /API_URL/g, replace: process.env['PLUNKER_API_URL'] },
                                { search: /EMBED_URL/g, replace: process.env['PLUNKER_EMBED_URL'] },
                                { search: /RUN_URL/g, replace: process.env['PLUNKER_RUN_URL'] },
                                { search: /SHOT_URL/g, replace: process.env['PLUNKER_SHOT_URL'] },
                                { search: /WWW_URL/g, replace: process.env['PLUNKER_WWW_URL'] },
    plugins: [
        new ExtractTextPlugin({
            filename: '[name].css',
            disable: false,
            allChunks: true,
        }),
    resolve: {
        modules: [
            Path.join(__dirname, 'node_modules'),
            Path.join(__dirname, 'src'),
module.exports = config;
jofftiquez, kbulygin, peterchealse, steinslin, mysticatea, arturparkhisenko, caszhou, augbog, givanse, imior, and 23 more reacted with thumbs up emoji baishiup and liuliangsir reacted with confused emoji peterchealse, lazyhero, srender, imior, swey, sbalay, zengkm, fi3ework, walmik, liuliangsir, and ajmeese7 reacted with heart emoji bigbossx and ajmeese7 reacted with rocket emoji All reactions

The way I see it, there are a few good solutions:

  • Make transform-runtime support outputting require statements instead of import statements, as an option. This seems unlikely, because it looks like Babel is already relying on the fact that import is declarative.
  • Use transform-es2015-modules-commonjs. This would replace all import statements with require statements. If you are not using any import/export syntax in your app, this solution is probably ideal, because it incurs no extra cost. However, if you are using ES modules, then this will likely impact Webpack 2's ability to perform tree shaking. (I'm sure everyone is aware of this.)
  • Use ES modules across the board. I think this is the most correct thing to do. Is there a reason why existing CommonJS exports can't simply be migrated? require does not have to be globally replaced, only module.exports and exports statements.
  • yuzhouwww, SmileSmith, patcheco1001, ejlofgren, drunkdreams, jaythomas, steinslin, balajikr1994, OldDream, ShehanEk, and 7 more reacted with thumbs up emoji luccastro reacted with laugh emoji luccastro reacted with hooray emoji peterchealse, caszhou, alexandre-lim, givanse, cy904159293, btzsoft, yuzhouwww, patcheco1001, ejlofgren, myhirra, and 2 more reacted with heart emoji luccastro and bitdom8 reacted with rocket emoji All reactions

    How i can reproduce module.exports behavior?
    I had entry point with name LoginPage, i need to build library with the same name, after that i init it on the page using new LoginPage();
    Now i should use new LoginPage.LoginPage() or new LoginPage.default();
    How i can resolve this issue?

    And was able to fix this by removing the add-module-exports plugin. TBH, I can't even recall why I had it in there to begin with... but upon removal it started working as expected. Nobody else has mentioned add-module-exports yet so I thought I'd chime in too to point out that it's not just transform-runtime causing this.

    jaythomas, foolyoghurt, jiawei686, lc-soft, oodzchen, crutchcorn, arcadiansc, fi3ework, janosvajda, glenselle, and 10 more reacted with thumbs down emoji abrenoch, ajmeese7, MaxInMoon, and jebadirad reacted with hooray emoji rumblefrog, dcasella, selfrenan, danny-andrews-snap, nobitagit, ChristophWurst, and-semakin, plemarquand, dbof10, calebeby, and 12 more reacted with confused emoji kourindouhime and IrfDev reacted with heart emoji usersaurus, tmladek, tobz1000, tabrez96, mohsinulhaq, lchean, OuKevin, bullettoothaxe, fkotsian, and IrfDev reacted with eyes emoji All reactions

    In my react-native-web case, just use an additional webpack rule, then the TypeError: Cannot assign to read only property 'exports' of object is fixed. Maybe you can ref to it.

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

    Create a config-overrides.js in your project root

    // 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;
    

    Also create a 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 = () => {};
    

    Now you can just run react-app-rewired start instead of react-scripts start

    Had a weird issue w/ imports or something when setting this up, that was
    solved with this: webpack/webpack#4039 (comment)
    Looks like it had to do w/ Babel transpiling (or not) modules in
    node_modules.
    Use a helper module with the links.  The culprit was that `require`
    doesn't mix with `module.exports`.
    You can mix require and export. You can't mix import and
    module.exports. webpack/webpack#4039 . Still
    have to see why index.js works fine though.
    Hardcoded module.exports breaks webpack when importing the ES module build.
    I've removed the add-module-exports plugin since it works only when the default export is the only export, which isn't the case for `stream-tag`.
    Instead, I'm patching the commonjs build after the fact.
    Related: webpack/webpack#4039
    …e build.
    I've removed the `add-module-exports` plugin since it works only when the default export is the only export, which isn't the case for `stream-tag`.
    Instead, I'm patching the commonjs build after the fact.
    Related: webpack/webpack#4039
    Hardcoded `module.exports` breaks webpack when importing the ES module build.
    I've removed the `add-module-exports` plugin since it works only when the default export is the only export, which isn't the case for `stream-tag`.
    Instead, I'm patching the commonjs build after the fact.
    Related: webpack/webpack#4039

    https://babeljs.io/docs/en/options#sourcetype

    "script" - Parse the file using the ECMAScript Script grammar. No import/export statements allowed, and files are not in strict mode.
    "module" - Parse the file using the ECMAScript Module grammar. Files are automatically strict, and import/export statements are allowed.
    "unambiguous" - Consider the file a "module" if import/export statements are present, or else consider it a "script".

    Given that the default for sourcetype is "module", I wonder why Babel doesn't treat the presence of module.exports (and the absence of import/export statements) as a signal that the file should be parsed as "script" instead, to avoid throwing this error.

    DB.prototype.limit = function(offset, limit) { this.offset = offset || 0; this.limit = limit || 15; return this; DB.prototype.sort = function(orderby) { this.orderby = orderby; return this; * query: Object类型 查询条件 支持使用比较运算符($lt, $lte, $gt, $gte, $in, $nin, $ne), 逻辑运算符 * offset: 偏移量 忽略多少条 用于分页 * limit: 返回条数 用于分页 * 返回: docs 数组 返回查询到的数据 * * */ DB.prototype.find = function(query, select) { return new Promise((resolve, reject) => { let stmt = this.db.find(query || {}); if (this.orderby !== undefined) { stmt.sort(this.orderby); if (this.offset !== undefined) { stmt.skip(this.offset).limit(this.limit); if (select != undefined) { stmt.projection(select || {}); stmt.exec((err, docs) => { if (err) { return reject(err); resolve(docs); }); }); * query: object 查询条件 * 查找一条 * 返回: 查到数据 * * */ DB.prototype.findOne = function(query, select) { return new Promise((resolve, reject) => { let stmt = this.db.findOne(query || {}); if (this.sort !== undefined) { stmt.sort(this.sort); if (select != undefined) { stmt.projection(select || {}); stmt.exec((err, doc) => { if (err) { return reject(err); resolve(doc); }); }); * 插入数据 * value: 插入的数据 * 使用array,实现批量插入。一旦其中一个操作失败,所有改变将会回滚。 * * */ DB.prototype.insert = function(values) { return new Promise((resolve, reject) => { this.db.insert(values, (err, newDoc) => { if (err) { return reject(err); resolve(newDoc); }); }); * 更新数据 * query: object 查询的数据 * values: 更新的数据 * options : object muti(默认false),是否允许修改多条文档;upsert(默认为false) * * */ DB.prototype.update = function(query, values, options) { return new Promise((resolve, reject) => { this.db.update( query || {}, values || {}, options || {}, (err, numAffected) => { if (err) { return reject(err); resolve(numAffected); }); * 根据options配置删除所有query匹配到的文档集。 * query: 与find和findOne中query参数的用法一致 * options: 只有一个可用。muti(默认false),允许删除多个文档 * * */ DB.prototype.remove = function(query, options) { return new Promise((resolve, reject) => { this.db.remove(query || {}, options || {}, (err, numAffected) => { if (err) { return reject(err); resolve(numAffected); }); }); // module.exports = (database) => { // return new DB(database); // }; const nedb = (database='testdb') => { return new DB(database); export default nedb
    const db = require("./nedb.js").default("testdb");
    Webpack incompatibility when running a calendar with react native web. Seemingly simple solution. wix/react-native-calendars#1518 change import to require - Cannot assign to read only property 'exports' of object '#<Object>' wix/react-native-calendars#1553
    Sharing tailwind config across react components is a bit of a pain.
    I could fix my issue after reading this one: tailwindlabs/tailwindcss#1853 that uses the preval plugin
    refs tailwindlabs/discuss#50 webpack/webpack#4039 storybookjs/storybook#5298
    …webpack@5 cause `Uncaught Error: ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: ./node_modules/@flyskywhy/react-native-gcanvas/index.js`, ref to
        webpack/webpack#4039 (comment)
    Error: ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: 581 #12549 fix(plugin-chart-handlebars): Update webpack/babel config to fix build/runtime warnings/errors apache/superset#21779