Parcel and rc-table breaks on production build

Viewed 313

I have created a sample react app from createapp.dev and added antd in the package.json.

I have been playing around with the table component from antd, and all worked fine when running locally. My snippet looks like this:

import React from 'react';
import {Table} from "antd";

export default class App extends React.Component {
  render() {
    return(
      <div>
        <div>Table</div>
        <Table dataSource={[]} columns={[]} />
      </div>
    )
  }
}

And the package.json is this:

{
"name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "keywords": [],
  "author": "",
  "license": "ISC",
  "scripts": {
    "clean": "rm dist/bundle.js",
    "start": "parcel src/index.html",
    "build": "parcel build src/index.html"
  },
  "dependencies": {
    "antd": "^4.8.2",
    "react": "^17.0.0",
    "react-dom": "^17.0.0"
  },
  "devDependencies": {
    "parcel-bundler": "^1.12.4",
    "@babel/core": "^7.12.3",
    "@babel/preset-env": "^7.12.1",
    "@babel/preset-react": "^7.12.1"
  }
}

Then after running yarn build command it successfully generates the build, but when serving the production build, it breaks with errors like TypeError: s is not a function which comes from Header component of rc-table.

I've searched for a workaround and but wasn't able to find a solution. Does that mean we can't use Table component from antd and why is this issue not detected when running the production build? Has anyone encountered a similar issue?

Edit: Found an online demo with a similar issue

1 Answers

The Parcel Bundler (1.x.x) does not support multiple JS files having the same content.

You can add the following script in scripts/fix-parcel-rc-table-issue.js. Then run it before each build (e.g. "build": "node fix-parcel-rc-table-issue.js && parcel build index.html". ).

const fs = require('fs')

const MARKER = 'CHANGE_CONTENT_HASH'

for (const file of ['BodyContext.js', 'ResizeContext.js', 'TableContext.js']) {
  const filePath = require.resolve(`rc-table/es/context/${file}`)
  const content = fs.readFileSync(filePath).toString()
  if (content.includes(MARKER)) {
    continue
  }
  const newContent =
    content + `\nfunction ${MARKER} () { return ${Math.random()} }`
  fs.writeFileSync(filePath, newContent)
}

Background

This exact issue has been reported to Ant Design as a bug. They did some digging and found the underlying parcel issue. Here you can find some details.

The Parcel developers don't want to fix this in 1.x.x, but are telling users to switch to the (currently) unstable 2.x.x version. This issue has some more details.

The Parcel developers suggest using the --experimental-scope-hoisting flag. This breaks my build, so I can't verify that this actually fixes the problem. I advise against using this flag in production as it's experimental, so it might have unexpected side-effects (in my opinion Parcels track record generally isn't very good).

Instead I followed FocusCare's advice and simply changed the contents of the files to be unique. This is a nasty hack though, but seems to be the best option until Parcel 2.x.x comes out (or you switch to a more mature bundler).

Related