sanyuan0704 / vite-plugin-chunk-split

A vite plugin for better chunk splitting. 一个简单易用的 Vite 拆包插件

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Cannot read properties of undefined (reading 'exports')

Profesor08 opened this issue · comments

If I try to use this plugin to split chunks, I get error in runtime, when start preview of build. There is something wrong in custom spliting (customSplitting).

Uncaught TypeError: Cannot read properties of undefined (reading 'exports')

image

chunkSplitPlugin({
      strategy: "single-vendor",
      customSplitting: {
        common: [/src\/ts\/utils/, /src\/ts\/components/],
        "react-common": [
          /src\/ts\/react-components/,
          /src\/ts\/react-hooks/,
          /src\/ts\/react-theme/,
          /src\/ts\/react-utils/,
        ],
      },
    })

Please check if it exists circular dependencies in your output chunk.

I don't have any errors or warnings about circular dependencies.

Can you provide a minimal demo that reproduce the problem?

I had the same problem when I wanted to package 'antd'

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { chunkSplitPlugin } from 'vite-plugin-chunk-split';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
      react(),
      chunkSplitPlugin({
      // 指定拆包策略
      customSplitting: {
        'react-vendor': ['react', 'react-dom'],
        'library': ['antd'],
      }
    })]
})

I found that this method was packaged into the ‘library’ and used in ‘react-vendor,’ resulting in a circular reference between the two。
image

demo

I had the same problem when I wanted to package 'antd'

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { chunkSplitPlugin } from 'vite-plugin-chunk-split';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
      react(),
      chunkSplitPlugin({
      // 指定拆包策略
      customSplitting: {
        'react-vendor': ['react', 'react-dom'],
        'library': ['antd'],
      }
    })]
})

I found that this method was packaged into the ‘library’ and used in ‘react-vendor,’ resulting in a circular reference between the two。 image

demo

@baiwusanyu-c I found the cause of the problem.In normal case, library chunk will import react-vendor chunk, and there are no circular dependency problem.

But @rollup/plugin-commonjs will be applied in production by default and it will inject some helper function in libray chunk, which leads to the result that react-vendor should import library chunk because react-vendor need this helper function as well.So circular dependency problem happends.

// commonjs helper function
function getDefaultExportFromCjs(x) {
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
}

Luckily, i fix the problem in vite-plugin-chunk-split@0.4.0 and internally split the commonjs helper function to a single chunk to avoid the circular dependency problem.

I had the same problem when I wanted to package 'antd'

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { chunkSplitPlugin } from 'vite-plugin-chunk-split';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
      react(),
      chunkSplitPlugin({
      // 指定拆包策略
      customSplitting: {
        'react-vendor': ['react', 'react-dom'],
        'library': ['antd'],
      }
    })]
})

I found that this method was packaged into the ‘library’ and used in ‘react-vendor,’ resulting in a circular reference between the two。 image
demo

@baiwusanyu-c I found the cause of the problem.In normal case, library chunk will import react-vendor chunk, and there are no circular dependency problem.

But @rollup/plugin-commonjs will be applied in production by default and it will inject some helper function in libray chunk, which leads to the result that react-vendor should import library chunk because react-vendor need this helper function as well.So circular dependency problem happends.

// commonjs helper function
function getDefaultExportFromCjs(x) {
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
}

Luckily, i fix the problem in vite-plugin-chunk-split@0.4.0 and internally split the commonjs helper function to a single chunk to avoid the circular dependency problem.

I tried it and the problem was solved, thanks

@sanyuan0704

Next config generates vendor.js and react-common.js, and they require each other. common.js - just pure functions, without imports, all is ok with it.

    chunkSplitPlugin({
      strategy: "single-vendor",
      customSplitting: {
        common: [/src\/ts\/utils/, /src\/ts\/components/],
        "react-common": [
          /src\/ts\/react-components/,
          /src\/ts\/react-hooks/,
          /src\/ts\/react-theme/,
          /src\/ts\/react-utils/,
        ],
      },
    }),

Result

react-common.js

import {R as ht, r as n, j as Ee, s as i, L as Xe, C as Te, c as _e, t as Je, a as mt, n as Ge, d as v, u as gt, o as ft, f as xt, b as wt, e as bt, g as yt, h as kt, i as Ct, k as vt, l as It, m as Ft, A as St, p as Bt} from "./vendor.js";
import {m as Et, c as Tt, f as Nt} from "./common.js";
const Mt = ht.createContext({ // Uncaught ReferenceError: Cannot access 'ht' before initialization
  sdfkjhsdf: "hjfdkfhgk"
})

vendor.js

import {g as Wf, c as Er} from "./__commonjsHelpers__.js";
import {j as Ft, a as pb, F as Qp} from "./react-common.js"; // I think there is something wrong

How vendor.js is generated and why it requre react-common.js?

May be it is because of react word in path? If it is true, then this bug easy to be fixed by comparing real path.

You can set build.minify = false, then it will be easier to see.

vendor.js

import {g as getDefaultExportFromCjs, c as commonjsGlobal} from "./__commonjsHelpers__.js";
import {j as jsx, a as jsxs, F as Fragment} from "./react-common.js";

react-common.js

import { R as React__default, r as react, j as jsxRuntime, s as styled, L as Link, C as Ce, c as cloneDeep_1, t as toJS, a as reaction, n as nanoid, d as darken, u as useFloating, o as offset, f as flip, b as shift, e as arrow, g as useInteractions, h as useClick, i as useHover, k as useFocus, l as useRole, m as useDismiss, A as AnimatePresence, p as motion } from "./vendor.js";
import { m as matchAll, c as constrain, f as formatCompact } from "./common.js";
const LangContext = React__default.createContext({
  sdfkjhsdf: "hjfdkfhgk"
});

I dont't know what jsx, jsxs and Fragment are doing in react-common.js. They must be in vendor.js.

maybe you should split react and react/jsx-runtime into a single chunk

Can you give a reproduction repo?

@Profesor08
for submodule, it's recommend to use regexp

I think I have found a solution: vitejs/vite#6215 (comment)

I don't know how it is related to chunks, but unnecesary import from vendor is gone.