Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

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

Decrease bundle size #1008

Closed
2 tasks done
WangLarry opened this issue Sep 15, 2022 · 9 comments · Fixed by #1881
Closed
2 tasks done

Decrease bundle size #1008

WangLarry opened this issue Sep 15, 2022 · 9 comments · Fixed by #1881
Labels

Comments

@WangLarry
Copy link

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Summary 💡

I use @next/bundle-analyzer to analyze toolpad-app. It show there are two huge packages: monaco-editor and @mui/icons-material.

截屏2022-09-15 19 19 08

截屏2022-09-15 19 20 11

Examples 🌈

No response

Motivation 🔦

No response

@WangLarry WangLarry added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Sep 15, 2022
@Janpot
Copy link
Member

Janpot commented Sep 15, 2022

  • monaco-editor is needed for the code editors. It's big because it contains a language server. It's in its own chunk and loaded asynchronously as a worker. I don't see a problem here.
  • @mui/icons-material is also in its own chunk and lazy loaded on the deployed application but only if the user uses icons in custom scripts.

@WangLarry
Copy link
Author

info  - Collecting page data  
Route (pages)                                Size     First Load JS
┌ λ /                                        1.16 kB         195 kB
├   /_app                                    0 B             119 kB
├ λ /_toolpad/[[...index]]                   330 kB         1.53 MB
├ λ /404                                     199 B           120 kB
├ λ /api/data/[appId]/[version]/[queryId]    0 B             119 kB
├ λ /api/dataSources/[dataSource]/[...path]  0 B             119 kB
├ λ /api/health-check                        0 B             119 kB
├ λ /api/rpc                                 0 B             119 kB
├ λ /app-canvas/[[...path]]                  2.92 kB         1.2 MB
├ λ /app/[appId]/[version]/[[...path]]       358 B           1.2 MB
└ λ /deploy/[appId]/[[...path]]              353 B           1.2 MB
+ First Load JS shared by all                119 kB
  ├ chunks/framework-2422bd4d7ba12811.js     45.9 kB
  ├ chunks/main-5b7e023216b20801.js          35 kB
  ├ chunks/pages/_app-5b8c0ac2d0c62fea.js    32 kB
  └ chunks/webpack-f2ca0da3ac4cec04.js       6.56 kB

ƒ Middleware                                 20.5 kB

@WangLarry
Copy link
Author

@Janpot
Copy link
Member

Janpot commented Sep 15, 2022

@WangLarry Are there any specific problems you'd like to point out?

@WangLarry
Copy link
Author

WangLarry commented Sep 15, 2022

235 request, too many.
Can optimize load @mui/material/* module, using the method of dealing @mui/icons-material

I have tested,it will decrease request times to 95

Are you understand? Sorry my bad english

@Janpot
Copy link
Member

Janpot commented Sep 15, 2022

Can optimize load @mui/material/* module, using the method of dealing @mui/icons-material

I'm not sure that would work well with imports like:

import Button, { buttonClasses } from "@mui/material/Button";

@WangLarry
Copy link
Author

WangLarry commented Sep 16, 2022

@Janpot


const muiMaterialExports = new Map<string, ExportMapValue>([
  ['@mui/material', import('@mui/material')],
  // ['@mui/material/Accordion', import('@mui/material/Accordion')],
  // ['@mui/material/CssBaseline', import('@mui/material/CssBaseline')],
  // ['@mui/material/List', import('@mui/material/List')],
  // ['@mui/material/Snackbar', import('@mui/material/Snackbar')],
  // ['@mui/material/ToggleButtonGroup', import('@mui/material/ToggleButtonGroup')],
  // ['@mui/material/AccordionActions', import('@mui/material/AccordionActions')],
  // ['@mui/material/Dialog', import('@mui/material/Dialog')],
  // ['@mui/material/ListItem', import('@mui/material/ListItem')],
  // ['@mui/material/SnackbarContent', import('@mui/material/SnackbarContent')],
  // ['@mui/material/Toolbar', import('@mui/material/Toolbar')],
  // ['@mui/material/AccordionDetails', import('@mui/material/AccordionDetails')],
  // ['@mui/material/DialogActions', import('@mui/material/DialogActions')],
  // ['@mui/material/ListItemAvatar', import('@mui/material/ListItemAvatar')],
  // ['@mui/material/SpeedDial', import('@mui/material/SpeedDial')],

....

      const compMatch = /^@mui\/material\/(.*)$/.exec(moduleId);
      if (compMatch) {
        const compName = compMatch[1];
        const compModule = modules.get('@mui/material');
        const compClasses = `${uncapitalize(compName)}Classes`;
        esModule = {
          default: (compModule as any)[compName],
          [compClasses]: (compModule as any)[compClasses],
        };
      }

截屏2022-09-16 09 48 02

@apedroferreira apedroferreira removed the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Sep 27, 2022
@Janpot
Copy link
Member

Janpot commented Oct 4, 2022

@WangLarry The point was that it requires us to hardcode the exports of each of those modules imported, which will be a maintenance burden as we'll have to keep it up to date as @mui/material evolves. So I don't feel like we should go that way. If the problem is the bundle splitting, we could organize the imports in a way that would create a single chunk for all library code:

// ./loadModule.ts

// ...
    const muiExports = await import('./muiExports')
// ...
import muiMaterialDefault, * as muiMaterial from '@mui/material';
import muiMaterialAccordionDefault, * as muiMaterialAccordion from '@mui/material/Accordion';
// ...

function esm(defaultExport: any, namedExports: any) {
  return { ...namedExports, default: defaultExport, __esModule: true };
}

export default new Map([
  ['@mui/material', esm(muiMaterial, muiMaterialDefault)],
  ['@mui/material/Accordion', esm(muiMaterialAccordionDefault, muiMaterialAccordion)],
  // ...
]);

It's still not great as it still imports all library code, even when unused, but it will use less requests. It also hacks esm support on top of commonjs which will for sure run into edge cases at some point. In the future we could look into either a pure ESM runtime that only loads used components, or a serverside compilation step for deployed applications.

@Janpot
Copy link
Member

Janpot commented Jun 12, 2023

Closing this issue as we have replaced the runtime with vite and are now compiling only the libraries that are being used.
See #1881

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants