vite icon indicating copy to clipboard operation
vite copied to clipboard

[Vite version 3.0.0-alpha.9]: Treeshaking does not work with libs.

Open zouhangwithsweet opened this issue 2 years ago • 14 comments

Describe the bug

[Vite version 3.0.0-alpha.9]: Cannot treeshaking libs. image

[Vite version 2.9.9]: Its ok. image

Reproduction

https://stackblitz.com/edit/vitejs-vite-bqjtx1?file=src%2FApp.tsx,vite.config.ts,stats.html

System Info

System:
    OS: macOS 11.6
    CPU: (8) arm64 Apple M1
    Memory: 99.69 MB / 8.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.13.0 - ~/.nvm/versions/node/v16.13.0/bin/node
    Yarn: 1.22.17 - ~/.nvm/versions/node/v16.13.0/bin/yarn
    npm: 8.1.0 - ~/.nvm/versions/node/v16.13.0/bin/npm
  Browsers:
    Chrome: 102.0.5005.61
    Safari: 14.1.2
  npmPackages:
    @vitejs/plugin-legacy: ^1.8.0 => 1.8.2 
    @vitejs/plugin-react: ^1.3.2 => 1.3.2 
    vite: ^3.0.0-alpha.9 => 3.0.0-alpha.9

Used Package Manager

pnpm

Logs

$ pnpm run build

> [email protected] build /Users/sun/Desktop/work/vite-antd-seed
> vite build

vite v3.0.0-alpha.9 building for production...
✓ 42 modules transformed.
dist/assets/favicon.4b63ffc1.svg        1.49 KiB
dist/index.html                         0.53 KiB
dist/assets/TestComponent.7cc13317.js   0.12 KiB / gzip: 0.13 KiB
dist/assets/index.0d2e4644.js           0.19 KiB / gzip: 0.17 KiB
dist/assets/index.2636713a.js           5.91 KiB / gzip: 2.51 KiB
dist/assets/esm-VW3YJATR.944f0927.js    214.24 KiB / gzip: 64.88 KiB
dist/assets/index.06cb8156.css          530.03 KiB / gzip: 67.17 KiB
dist/assets/vendor.8dd48daa.js          1696.88 KiB / gzip: 538.35 KiB

(!) Some chunks are larger than 500 KiB after minification. Consider:
- Using dynamic import() to code-split the application
- Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/guide/en/#outputmanualchunks
- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.

Validations

zouhangwithsweet avatar Jun 04 '22 13:06 zouhangwithsweet

The solution I found to this, prior to Vite Alpha-11 was to provide all files as entry point within build -> rollupOptions -> input as well as correcting import paths manually. At Alpha-11 I had to implement build -> rollupOptions -> output -> manualChunks with the following to resolve this issue.

  • SourceRoot and NodeModulesRoot should be adjusted to point at the base of your source code. In most projects this is the src directory.
  • .ts files are assumed to be entry points
  • SourceRoot directory structure will be copied
import { extname, resolve } from "path";

export class ManualChuncker {
  // Project
  private static readonly SupportedFiles = [
    "ts",
    "vue",
    "scss",
    "scss?inline",
    "js",
    "json",
  ];
  private static readonly SourceRoot = resolve(
    __dirname,
    "..",
    "library",
    "api"
  );
  private static readonly NodeModulesRoot = resolve(
    __dirname,
    "..",
    "node_modules"
  );

  // Generated
  private static readonly AssetDir = "_assets/";
  private static readonly NodeModuleDir = "_external/";
  private static readonly PluginDir = "_plugins/";
  private static readonly VueDir = "_vue/";

  public static resolve(path: string) {
    return new ManualChuncker(path).resolve();
  }

  constructor(public readonly path: string) {}

  public resolve(): string | void {
    return this.moduleName;
  }

  private get moduleName() {
    const CleanPath = this.path.substring(
      0,
      this.path.length - extname(this.path).length
    );
    if (this.isNodeModule) {
      return `${ManualChuncker.NodeModuleDir}${CleanPath.substring(
        ManualChuncker.NodeModulesRoot.length + 1
      )}`;
    }

    if (this.isVue) {
      return `${ManualChuncker.VueDir}${CleanPath.substring(
        ManualChuncker.SourceRoot.length + 1
      )}`;
    }

    if (this.isAsset) {
      return `${ManualChuncker.AssetDir}${CleanPath.substring(
        ManualChuncker.SourceRoot.length + 1
      )}`;
    }

    if (this.isPlugin) {
      return `${ManualChuncker.PluginDir}${this.path}`;
    }

    return CleanPath.substring(ManualChuncker.SourceRoot.length + 1);
  }

  private get isNodeModule() {
    return this.path.startsWith(ManualChuncker.NodeModulesRoot);
  }

  private get isAsset() {
    return (
      this.fileType === "scss" ||
      this.fileType === "json" ||
      this.fileType === "scss?inline"
    );
  }

  private get isVue() {
    return this.path.endsWith(".vue");
  }

  private get isPlugin() {
    return !ManualChuncker.SupportedFiles.map((ext) =>
      this.path.endsWith(`.${ext}`)
    ).includes(true);
  }

  private get fileType():
    | typeof ManualChuncker["SupportedFiles"][number]
    | null {
    const ext = extname(this.path).substring(1);

    if (ManualChuncker.SupportedFiles.includes(ext)) {
      return ext as typeof ManualChuncker["SupportedFiles"][number];
    }

    return null;
  }
}

P.S. yarn publish doesn't seem to like the node_modules folder create (node_modules/vite/deps_build-dist) when you use the dist folder as the root of the package when deploying.

lukemovement avatar Jun 16 '22 12:06 lukemovement

I'm not sure if it's related to this problem. When I run vite build for the first time, the packaged files are obviously not as big as those of the second vite build.

I can't reproduce this issue in a newly created project, below are screenshots of two runs what could be the problem?

  • When the generated .vite folder does not exist under node_module 177530123-3c475208-eed6-407d-8c95-c19fbdd11efd
  • When the generated .vite folder exists under node_module 177530327-80cc6abe-92ee-4d78-9997-adc0ea3aa563

I suspect it has something to do with the cache. When I set optimizeDeps.force to true, the files output by each build are different but the size is very close

截屏2022-07-07 16 35 03

ckvv avatar Jul 07 '22 06:07 ckvv

^ I have the same problem

consegrado avatar Jul 07 '22 07:07 consegrado

@ckvv @consegrado, would you share a repro as minimal as possible so we can build a bench for these issues. Thanks!

patak-dev avatar Jul 07 '22 07:07 patak-dev

@patak-dev
This is a private project, and when I delete the src directory and add a simple case, the problem is not reproduced

ckvv avatar Jul 07 '22 07:07 ckvv

@ckvv would you try with:

  • https://github.com/vitejs/vite/pull/8965

patak-dev avatar Jul 07 '22 09:07 patak-dev

@patak-dev

When I set optimizeDeps.disabled = "build", vite build throws an error 截屏2022-07-07 17 21 20

ckvv avatar Jul 07 '22 09:07 ckvv

Have you tried https://github.com/vitejs/vite/pull/8965? Please open a new issue with a reproduction if you find a bug when using it

patak-dev avatar Jul 07 '22 09:07 patak-dev

@patak-dev updated to 3.0.0-beta.8 solved my problem

ckvv avatar Jul 08 '22 10:07 ckvv

Thanks for testing @ckvv, we'll review the tree-shaking issues and try to flip the default in v4 to optimize deps again 👍🏼 Let's keep this issue open to track the problem

patak-dev avatar Jul 08 '22 10:07 patak-dev

image Woo! Great work of your team.

zouhangwithsweet avatar Jul 08 '22 11:07 zouhangwithsweet

tree shaking does not work in 3.0.0-beta.8 and 3.0.0-beta.10

stavalfi avatar Jul 16 '22 09:07 stavalfi

tree shaking does not work in 3.0.0-beta.8 and 3.0.0-beta.10

Have you tried 3.0.0 (non-beta/alpha)? Wasn't previously working for me with the alpha, but works perfectly fine with the major release.

lrstanley avatar Jul 16 '22 19:07 lrstanley

I tried 3.0.0-beta.8 and 3.0.0-beta.10 and 3.0.0 and 3.0.2,tree shaking does not work

rainydayDY avatar Jul 22 '22 08:07 rainydayDY

@patak-dev I recently hit a similar issue, where I had a third party library which could have been completely tree shaken out but was not. And enabling dep optimiser manually did fix the issue.

It was a bit weird for me, as I expected better tree shaking without dep optimisation, as I believe dep optimisation is done without knowledge of what is actually imported from the lib.

jiby-aurum avatar Sep 30 '22 11:09 jiby-aurum

I'm on vite 3.1.0 and tree shaking not working at all

import { fill } from "lodash";
console.log(fill([], ""));

will includes all the lodash functions

kresli avatar Oct 06 '22 13:10 kresli

@kresli please share your configuration, I had to manually enable dependency optimisation to get tree shaking in lib mode

{
  optimizeDeps: {
    disabled: false
  },
  build: {
    commonjsOptions: {
      include: [],
    },
    rollupOptions: {
      treeshake: 'smallest',
    }
  }
}

jiby-aurum avatar Oct 06 '22 13:10 jiby-aurum

@kresli tree-shaking doesn't work on lodash (it has nothing to do with vite, rollup, or esbuild). For those who want tree-shaking with lodash, there's lodash-es package.

o-alexandrov avatar Nov 13 '22 13:11 o-alexandrov