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

Lib mode format: es.min #6555

Open
4 tasks done
yyx990803 opened this issue Jan 18, 2022 · 24 comments · May be fixed by #6585 or #18737
Open
4 tasks done

Lib mode format: es.min #6555

yyx990803 opened this issue Jan 18, 2022 · 24 comments · May be fixed by #6585 or #18737
Labels
enhancement New feature or request feat: library mode

Comments

@yyx990803
Copy link
Member

yyx990803 commented Jan 18, 2022

Clear and concise description of the problem

Currently when building in lib mode we do not minify the ES build because that would remove pure annotations and break treeshaking. However, this is assuming that the ES build is only used with bundlers. In the future, more users could be using ES builds over CDNs with native ES imports, so a minified ES build could be necessary for those cases.

Suggested solution

// vite config
build: {
  lib: {
    formats: ['es', 'es.min']
  }
}

Alternative

lib: { minifyES: true }

Additional context

vuejs/petite-vue#112

Validations

@Niputi
Copy link
Contributor

Niputi commented Jan 18, 2022

prior related #5167 #6314

@Bigfish8 Bigfish8 linked a pull request Jan 21, 2022 that will close this issue
9 tasks
@Kurtil
Copy link

Kurtil commented Jan 28, 2022

What about #6670 ? :P

ohmree added a commit to ohmree/tagin that referenced this issue Feb 8, 2022
This commit also makes it possible to import the source SCSS styles from
dependent code.

Caveats/differences from previous setup:
 - `dist/tagin.module.min.js` isn't actually minified - see vitejs/vite#6555.
 - no css sourcemap are generated - see vitejs/vite#2830.
@bluwy bluwy mentioned this issue Apr 11, 2022
9 tasks
@bluwy
Copy link
Member

bluwy commented Jun 24, 2022

In #8754, I've updated so that minifyWhitespace would only be turned off (which is removing the pure annotations). minifySyntax and minifyIdentifiers are enabled so we have partial minification for es lib build.

@Junior2Ran
Copy link

is there any progress about this topic?

@mindplay-dk
Copy link

I don't understand, is minifying just disabled entirely for es library output?

I've tried for example this:

  build: {
    lib: {
      // ...
      formats: ["es"]
    },
    minify: "terser",
    terserOptions: {
      compress: true,
      mangle: true,
    },
  }

It doesn't minify or mangle at all - I have no control of the terser options at all?

I can understand having sensible defaults, so you don't accidentally break tree shaking - but blocking me from configuring terser entirely? And not even a warning - it just doesn't work. Very confusing.

At this time, minify: "esbuild" gives a significantly smaller file, because it actually compresses and minifies - with minify: "terser" it doesn't minify at all. How is this setting useful?

I was able to manually minify with terser after the fact, so it's not that this isn't possible.

npm exec terser -- -c -m --module dist/lib.js > dist/lib.min.js

@Teaghy
Copy link

Teaghy commented Dec 2, 2022

Excuse me, has this problem been solved yet?

@abarke
Copy link

abarke commented Dec 7, 2022

Any solution?

@soerenmeier
Copy link

As a workaround you can use a small plugin to minify the file:

import esbuild from 'esbuild';

const plugin = {
	name: 'minify',
	closeBundle: () => {
		esbuild.buildSync({
			entryPoints: ['./dist/lib.js'],
			minify: true,
			allowOverwrite: true,
			outfile: './dist/lib.js'
		})
	}
};

@sinedied
Copy link

sinedied commented Dec 8, 2022

Would love to see this implemented!

Currently this is my workaround:

Add an extra esm format to lib entry (don't mind the TS error):

    lib: {
      entry: './src/index.ts',
      formats: ['es', 'esm'],
      fileName: (format) => ({
        es: `${pkg.name}.js`,
        esm: `${pkg.name}.min.js`,
      })[format]

Then add this plugin to the build:

import { transform } from 'esbuild';

function minifyEs() {
  return {
    name: 'minifyEs',
    renderChunk: {
      order: 'post',
      async handler(code, chunk, outputOptions) {
        if (outputOptions.format === 'es' && chunk.fileName.endsWith('.min.js')) {
          return await transform(code, { minify: true });
        }
        return code;
      },
    }
  };
}

This will generate the ES amd ES minified variants.

@maranomynet
Copy link

maranomynet commented Dec 8, 2022

@sinedied Thanks.

I've got //@ts-check at the top of my vite.config.js and to suppress the TS error I use this:

  formats: [
    'cjs',
    // @ts-expect-error
    'esm',
    // @ts-expect-error
    'system',
  ],

(BTW: 'system' format is supported by rollup and seems to work, despite vite not documenting it as an option.)

@abarke
Copy link

abarke commented Dec 9, 2022

Please support #6585

@YornQiu
Copy link

YornQiu commented Apr 17, 2023

so stupid, there is no way to minify 'es', terserOptions' compress and mangle doesn't work at all.

@stfn00
Copy link

stfn00 commented Jul 4, 2023

If it helps, I've made a custom plugin that implements terser on generateBundle phase, to minify.

import { resolve } from 'node:path'
import { defineConfig } from 'vite'
import { minify } from "terser";
import autoprefixer from 'autoprefixer'

function minifyBundles() {
  return {
    name: "minifyBundles",
    async generateBundle(options, bundle) {
      for (let key in bundle) {
        if (bundle[key].type == 'chunk' && key.endsWith('.js')) {
          const minifyCode = await minify(bundle[key].code, { sourceMap: false })
          bundle[key].code = minifyCode.code
        }
      }
      return bundle
    },
  }
}

export default defineConfig({
  appType: 'custom',
  css: {
    devSourcemap: true,
    postcss: {
      plugins: [
        autoprefixer
      ],
    }
  },
  build: {
    target: ['es2015'],
    outDir: 'dist',
    emptyOutDir: true,
    cssCodeSplit: true,
    sourcemap: false,
    lib: {
      formats: ['es'],
      entry: [
        resolve(__dirname, 'src/scripts/main.js'),
        resolve(__dirname, 'src/scripts/critical.js'),
      ],
      fileName: '[name]',
    },
  },
  plugins: [
    minifyBundles()
  ]
})

@itssumitrai
Copy link

Coming back end of 2023, this is a fairly important missing feature. For modern libraries esm is the way to go and no way to minify the output just makes it useless. Sticking to rollup for builds is the way to go atm

@daraclare
Copy link

Is there any plan to look at this does anyone know?

@Kurtil
Copy link

Kurtil commented Apr 17, 2024

Is there any plan to look at this does anyone know?

No news. This is my npm run build command workaround :

vite build && esbuild my/lib/path.js --minify --outfile=my/lib/path.js --allow-overwrite

I build using vite then minify using esbuild separatly... :/

@mindplay-dk
Copy link

In the future, more users could be using ES builds over CDNs with native ES imports, so a minified ES build could be necessary for those cases.

2.5 years on, this is beginning to feel like a pressing matter.

@stefanholzapfel
Copy link

Maybe I got something wrong, but why not use the minify flag directly in the build options?

    build: {
        outDir: './dist/bundle-minified',
        target: ['es2015'],
        lib: {
            entry: 'src/index.ts',
            formats: ['es', 'amd'],
            fileName: (format) => ({
                es: `spotteron.ui.esm.min.js`,
                amd: `spotteron.ui.amd.min.js`,
            })[format]
        },
        rollupOptions: {
            output: {
                inlineDynamicImports: true
            }
        },
        sourcemap: false,
        minify: true,
        cssMinify: true
    }

I get a minified version. Is the configurability the problem?

@krasevych
Copy link

any update?

@jmlee2k
Copy link
Contributor

jmlee2k commented Jun 19, 2024

This is yet another example of a small plugin which will minify the lib - I haven't tested it beyond my very simple use case.

benefits:

  • it doesn't rely on having to repeat the dist file name(s)
  • it uses esbuild for minification (which the eventual es.min solution will likely do, making it easier to move over once it's implemented)
const minifyBundle = ():Plugin=>({
	name:"minify-bundle",
	async generateBundle(_,bundle)
	{
		for (const asset of Object.values(bundle))
		{
			if (asset.type == "chunk")
				asset.code = (await esbuild.transform(asset.code,{minify:true})).code;
		}
	}
});

@Makio64
Copy link

Makio64 commented Aug 21, 2024

Thanks @jmlee2k the code you provide works for me

This said : being allow to minify a lib file should be by default for a bundler ?

@WIStudent
Copy link

In my case, I need to bundle a script that is directly imported by the browser somewhere else (so no further tree-shaking). I noticed that the es build is almost twice the size of the iife build.

iife: 374.14 kB
es: 608.17 kB

if (isEsLibBuild) {
// Disable minify whitespace as it breaks tree-shaking
return {
...options,
minify: false,
minifyIdentifiers: options.minifyIdentifiers ?? true,
minifySyntax: options.minifySyntax ?? true,
minifyWhitespace: false,
treeShaking: true,
}
} else {
return {
...options,
minify: false,
minifyIdentifiers: options.minifyIdentifiers ?? true,
minifySyntax: options.minifySyntax ?? true,
minifyWhitespace: options.minifyWhitespace ?? true,
treeShaking: true,
}
}
}

Wouldn't changing line 429 to minifyWhitespace: options.minifyWhitespace ?? false solve this issue? That way, anyone who wants the smallest bundle and doesn't need further tree-shaking could set

esbuild: {
  minifyWhitespace: true
}

explicitly in their vite config.

WIStudent added a commit to WIStudent/vite that referenced this issue Nov 22, 2024
fix vitejs#6555)

To produce es bundles that can be tree-shaken, lib mode disables
minifyWhitespace by default when using the es format. But there are
cases where we want an es bundle that is as small as possible and that
does not need to be tree-shakable. This change allows minifyWhitespace
to be re-enabled if the user so desires.
@WIStudent
Copy link

I opened a pull request that would make it possible to re-enable whitespace minification by setting

esbuild: {
  minifyWhitespace: true
}

@dteoh
Copy link

dteoh commented Nov 28, 2024

At the moment I've been using this kind of config instead of lib mode to serve ESM in a CDN-like manner:

export default defineConfig({
  build: {
    rollupOptions: {
      input: resolve(__dirname, "src/index.js"),
      output: {
        assetFileNames: (chunkInfo) => {
          return "[name][extname]";
        },
        entryFileNames: "[name].js",
      },
      preserveEntrySignatures: "strict",
    },
    sourcemap: true,
  },
});

Seems to work, but I am also not sure if I am missing some key information regarding why we cannot minify in lib mode.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request feat: library mode
Projects
None yet