vitejs / vite

Next generation frontend tooling. It's fast!
http://vite.dev
MIT License
67.85k stars 6.11k forks source link

About @vitejs/plugin-legacy does not support library mode #1639

Open gjactat opened 3 years ago

gjactat commented 3 years ago

Is your feature request related to a problem? Please describe. I'm a long time user of Vue in a webpack context and i'm giving a try to Vite. So far It's been a pleasant journey : Dev mode is really impressive !

My project consists of several standalone Vue components that are instantiated on demand from Vanilla Javascript. This is why they are currently built with the Webpack Library mode which works just fine.

I have successfully built these components with Vite (with dynamic import and everything) and they work juts fine on modern browser.

Describe the solution you'd like I'd like to also build those components for legacy browsers... And this is currently not allowed (error message : "@vitejs/plugin-legacy does not support library mode").

I'd like to know if there is still hope for this specific use case ?... And I also like to mention that these legacy builds don't have to be as polished as the es ones (considering that they will only be served to a small percentage of our visitors).

While I wish to give the best experience to the vast majority of my users (equipped with modern browsers), I would be fine with monolithic builds, without any code splitting or dynamic imports for legacy browsers. Maybe with something like Rollup's "inlineDynamicImports" ? After all, these legacy builds should vanish eventually.

Describe alternatives you've considered

Additional context Add any other context or screenshots about the feature request here.

Jeaciaz commented 3 years ago

Would love to see this implemented. As a developer who has to support IE11, Vite and its out-of-the-box speed and ease of use has been a blessing until I learned library mode doesn't support IE11 :(

stefandesu commented 3 years ago

I've been trying to get my library that was built with Vite working with https://observablehq.com, but so far to no avail. I thought maybe a legacy build would help, but unfortunately, that doesn't work at the moment as discussed here. 🤔

lovasoa commented 3 years ago

Hello ! @yyx990803 : what do you think would be needed to get that to work ? I have users on sanipasse.fr who are on old browsers and for whom the site is currently broken. I would be happy to contribute, but have no idea where to start.

tylerrrkd commented 2 years ago

Would love to see this implemented. As a developer who has to support IE11, Vite and its out-of-the-box speed and ease of use has been a blessing until I learned library mode doesn't support IE11 :(

Hope support soon.

skyweaver213 commented 2 years ago

Hope support soon.

lovasoa commented 2 years ago

Happy birthday to this issue 🎈🥳

fychinesepjj commented 2 years ago

Hope support soon.

wenjoy commented 2 years ago

IMHO, app which import the lib should care about to bunde it to be capable of old browser. It's not like build a site. So @vitejs/plugin-legacy doesn't need to support some IE 11. Thoughts?

wenjoy commented 2 years ago

I have figured out a solution to bundle lib supporting old browser without dependent @vitejs/plugin-legacy although I insist that lib no need to worry about it.

Here is a sample config, hope to help anyone encountered this:

//vite.config.js
import { babel } from '@rollup/plugin-babel';
...
 plugins: [
    babel({
      babelHelpers: 'runtime',
      extensions: ['.js', '.jsx', '.es6', '.es', '.mjs', 'ts'],
    })
]
//babel.config.js

module.exports = {
  presets: [
    [
      '@babel/env',
      {
        useBuiltIns: 'usage',
        corejs: 3,
      },
    ],
  ],
  plugins: ['@babel/plugin-transform-runtime'],
};
//package.json
  "browserslist": [
    "> 0.5%",
    "not dead"
  ],
agileago commented 2 years ago

@wenjoy ts is ok ? i think esbuild will deal the ts file but babel will not

wenjoy commented 2 years ago

@wenjoy ts is ok ? i think esbuild will deal the ts file but babel will not

esbuild will not transform to es5, but we cant config to let babel can handle ts even transform to es5.

agileago commented 2 years ago

我知道,你测试过这样写会进行转换ts么

gyurielf commented 2 years ago

@wenjoy ts is ok ? i think esbuild will deal the ts file but babel will not

esbuild will not transform to es5, but we cant config to let babel can handle ts even transform to es5.

But the question is how ? :D

xjccc commented 2 years ago

@wenjoy ts is ok ? i think esbuild will deal the ts file but babel will not

esbuild will not transform to es5, but we cant config to let babel can handle ts even transform to es5.

But the question is how ? :D i tried, but the error told me Rollup failed to resolve import "@babel/runtime/helpers/typeof"

eleven-net-cn commented 2 years ago

The following method should solve the problem, e.g:

// vite.config.js (e.g)
const { getBabelOutputPlugin } = require('@rollup/plugin-babel');

export default {
  build: {
    rollupOptions: {
      plugins: [
        /**
         * Running Babel on the generated code:
         *  https://github.com/rollup/plugins/blob/master/packages/babel/README.md#running-babel-on-the-generated-code
         *
         * Transforming ES6+ syntax to ES5 is not supported yet, there are two ways to do:
         *  https://github.com/evanw/esbuild/issues/1010#issuecomment-803865232
         * We choose to run Babel on the output files after esbuild.
         *
         * @vitejs/plugin-legacy does not support library mode:
         *  https://github.com/vitejs/vite/issues/1639
         */
        getBabelOutputPlugin({
          allowAllFormats: true,
          presets: [
            [
              '@babel/preset-env',
              {
                useBuiltIns: false, // Default:false
                // Exclude transforms that make all code slower
                exclude: ['transform-typeof-symbol'],
                // https://babeljs.io/docs/en/babel-preset-env#modules
                modules: false,
              },
            ],
          ],
          plugins: [
            /**
             * Extract the helper function.
             */
            [
              '@babel/plugin-transform-runtime',
              {
                corejs: false,
                // version: require('@babel/runtime').version,
              },
            ],
          ],
        }),
      ],
    },
  },
};

Running babel on the generated code by esbuild (vite).

The presets and plugins configuration of babel is only suitable for me, you can modify it.

jiakangning commented 2 years ago

I have figured out a solution to bundle lib supporting old browser without dependent @vitejs/plugin-legacy although I insist that lib no need to worry about it.

Here is a sample config, hope to help anyone encountered this:

//vite.config.js
import { babel } from '@rollup/plugin-babel';
...
 plugins: [
    babel({
      babelHelpers: 'runtime',
      extensions: ['.js', '.jsx', '.es6', '.es', '.mjs', 'ts'],
    })
]
//babel.config.js

module.exports = {
  presets: [
    [
      '@babel/env',
      {
        useBuiltIns: 'usage',
        corejs: 3,
      },
    ],
  ],
  plugins: ['@babel/plugin-transform-runtime'],
};
//package.json
  "browserslist": [
    "> 0.5%",
    "not dead"
  ],

its useful for js application when use vite

dparker2 commented 1 year ago

IMHO, app which import the lib should care about to bunde it to be capable of old browser. It's not like build a site. So @vitejs/plugin-legacy doesn't need to support some IE 11. Thoughts?

This rationale does not consider building a UMD formatted bundle (which is one of the default build formats), or an IIFE format, both of which can be directly included onto a page in older browsers.

woai3c commented 1 year ago

it's work for me:

pnpm i -D @babel/plugin-transform-runtime @babel/preset-env @babel/runtime @rollup/plugin-babel
// vite.config.ts
import { fileURLToPath, URL } from 'node:url'
import { resolve } from 'path'
import type { ConfigEnv, UserConfigExport } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import svgLoader from 'vite-svg-loader'
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
import babel from '@rollup/plugin-babel'

export default ({ command, mode }: ConfigEnv): UserConfigExport => {
    const config: UserConfigExport = {
        plugins: [vue(), vueJsx(), cssInjectedByJsPlugin(), svgLoader()],
        resolve: {
            alias: {
                '@': fileURLToPath(new URL('./src', import.meta.url)),
            },
        },
        build: {
            minify: 'terser',
            terserOptions: {
                compress: {
                    drop_console: true,
                    drop_debugger: true,
                },
            },
            lib: {
                entry: resolve(__dirname, 'src/index.ts'),
                name: 'IntegrationPlatformNavbar',
                fileName: 'integration-platform-navbar',
            },
            rollupOptions: {
                // 确保外部化处理那些你不想打包进库的依赖
                external: ['vue', 'element-plus'],
                output: {
                    // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
                    globals: {
                        vue: 'Vue',
                        'element-plus': 'ElementPlus',
                    },
                },
                plugins: [
                    babel({
                        extensions: ['.js', '.ts', '.vue'],
                        babelHelpers: 'runtime',
                        plugins: ['@babel/plugin-transform-runtime'],
                        presets: [
                            [
                                '@babel/preset-env',
                                {
                                    useBuiltIns: false,
                                    targets: {
                                        browsers: ['last 2 versions', '> 1%', 'not ie <= 11'],
                                    },
                                },
                            ],
                        ],
                    }),
                ],
            },
        },
    }

    return config
}
gaomAndximi commented 11 months ago

it's work for me:

pnpm i -D @babel/plugin-transform-runtime @babel/preset-env @babel/runtime @rollup/plugin-babel
// vite.config.ts
import { fileURLToPath, URL } from 'node:url'
import { resolve } from 'path'
import type { ConfigEnv, UserConfigExport } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import svgLoader from 'vite-svg-loader'
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
import babel from '@rollup/plugin-babel'

export default ({ command, mode }: ConfigEnv): UserConfigExport => {
    const config: UserConfigExport = {
        plugins: [vue(), vueJsx(), cssInjectedByJsPlugin(), svgLoader()],
        resolve: {
            alias: {
                '@': fileURLToPath(new URL('./src', import.meta.url)),
            },
        },
        build: {
            minify: 'terser',
            terserOptions: {
                compress: {
                    drop_console: true,
                    drop_debugger: true,
                },
            },
            lib: {
                entry: resolve(__dirname, 'src/index.ts'),
                name: 'IntegrationPlatformNavbar',
                fileName: 'integration-platform-navbar',
            },
            rollupOptions: {
                // 确保外部化处理那些你不想打包进库的依赖
                external: ['vue', 'element-plus'],
                output: {
                    // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
                    globals: {
                        vue: 'Vue',
                        'element-plus': 'ElementPlus',
                    },
                },
                plugins: [
                    babel({
                        extensions: ['.js', '.ts', '.vue'],
                        babelHelpers: 'runtime',
                        plugins: ['@babel/plugin-transform-runtime'],
                        presets: [
                            [
                                '@babel/preset-env',
                                {
                                    useBuiltIns: false,
                                    targets: {
                                        browsers: ['last 2 versions', '> 1%', 'not ie <= 11'],
                                    },
                                },
                            ],
                        ],
                    }),
                ],
            },
        },
    }

    return config
}

it works!

GrinZero commented 11 months ago

When I use useBuiltIns:"useage",It can't run......

GrinZero commented 11 months ago

In fact, it look like import"core-js/modules/esnext.global-this.js"; in my bundle file.But I want to use "inline" mode.

Lpmvb commented 10 months ago

it's work for me:

pnpm i -D @babel/plugin-transform-runtime @babel/preset-env @babel/runtime @rollup/plugin-babel
// vite.config.ts
import { fileURLToPath, URL } from 'node:url'
import { resolve } from 'path'
import type { ConfigEnv, UserConfigExport } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import svgLoader from 'vite-svg-loader'
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
import babel from '@rollup/plugin-babel'

export default ({ command, mode }: ConfigEnv): UserConfigExport => {
    const config: UserConfigExport = {
        plugins: [vue(), vueJsx(), cssInjectedByJsPlugin(), svgLoader()],
        resolve: {
            alias: {
                '@': fileURLToPath(new URL('./src', import.meta.url)),
            },
        },
        build: {
            minify: 'terser',
            terserOptions: {
                compress: {
                    drop_console: true,
                    drop_debugger: true,
                },
            },
            lib: {
                entry: resolve(__dirname, 'src/index.ts'),
                name: 'IntegrationPlatformNavbar',
                fileName: 'integration-platform-navbar',
            },
            rollupOptions: {
                // 确保外部化处理那些你不想打包进库的依赖
                external: ['vue', 'element-plus'],
                output: {
                    // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
                    globals: {
                        vue: 'Vue',
                        'element-plus': 'ElementPlus',
                    },
                },
                plugins: [
                    babel({
                        extensions: ['.js', '.ts', '.vue'],
                        babelHelpers: 'runtime',
                        plugins: ['@babel/plugin-transform-runtime'],
                        presets: [
                            [
                                '@babel/preset-env',
                                {
                                    useBuiltIns: false,
                                    targets: {
                                        browsers: ['last 2 versions', '> 1%', 'not ie <= 11'],
                                    },
                                },
                            ],
                        ],
                    }),
                ],
            },
        },
    }

    return config
}

replaceAll not be polyfill

yin-shu commented 8 months ago

it's work for me:这对我有用:

pnpm i -D @babel/plugin-transform-runtime @babel/preset-env @babel/runtime @rollup/plugin-babel
// vite.config.ts
import { fileURLToPath, URL } from 'node:url'
import { resolve } from 'path'
import type { ConfigEnv, UserConfigExport } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import svgLoader from 'vite-svg-loader'
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
import babel from '@rollup/plugin-babel'

export default ({ command, mode }: ConfigEnv): UserConfigExport => {
    const config: UserConfigExport = {
        plugins: [vue(), vueJsx(), cssInjectedByJsPlugin(), svgLoader()],
        resolve: {
            alias: {
                '@': fileURLToPath(new URL('./src', import.meta.url)),
            },
        },
        build: {
            minify: 'terser',
            terserOptions: {
                compress: {
                    drop_console: true,
                    drop_debugger: true,
                },
            },
            lib: {
                entry: resolve(__dirname, 'src/index.ts'),
                name: 'IntegrationPlatformNavbar',
                fileName: 'integration-platform-navbar',
            },
            rollupOptions: {
                // 确保外部化处理那些你不想打包进库的依赖
                external: ['vue', 'element-plus'],
                output: {
                    // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
                    globals: {
                        vue: 'Vue',
                        'element-plus': 'ElementPlus',
                    },
                },
                plugins: [
                    babel({
                        extensions: ['.js', '.ts', '.vue'],
                        babelHelpers: 'runtime',
                        plugins: ['@babel/plugin-transform-runtime'],
                        presets: [
                            [
                                '@babel/preset-env',
                                {
                                    useBuiltIns: false,
                                    targets: {
                                        browsers: ['last 2 versions', '> 1%', 'not ie <= 11'],
                                    },
                                },
                            ],
                        ],
                    }),
                ],
            },
        },
    }

    return config
}

我这样配置后,构建产物里有旧浏览器不支持的语法:

 var createPropertyDescriptor$8 = function createPropertyDescriptor2(bitmap, value) {
    return {
      enumerable: !(bitmap & 1),
      configurable: !(bitmap & 2),
      writable: !(bitmap & 4),
      value
    };
  };

这里的 'value' 在旧浏览器中不兼容,这些代码应该是babel 加入进去的,很奇怪,我使用版本是:

"@babel/plugin-transform-runtime": "^7.23.7",
    "@babel/preset-env": "^7.23.8",
    "@babel/runtime": "^7.23.8",
    "@babel/runtime-corejs3": "^7.23.8",
    "@rollup/plugin-babel": "^5.3.1",
    "vite": "^5.0.11",
yoyo837 commented 8 months ago

it's work for me:这对我有用:

pnpm i -D @babel/plugin-transform-runtime @babel/preset-env @babel/runtime @rollup/plugin-babel
// vite.config.ts
import { fileURLToPath, URL } from 'node:url'
import { resolve } from 'path'
import type { ConfigEnv, UserConfigExport } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import svgLoader from 'vite-svg-loader'
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
import babel from '@rollup/plugin-babel'

export default ({ command, mode }: ConfigEnv): UserConfigExport => {
    const config: UserConfigExport = {
        plugins: [vue(), vueJsx(), cssInjectedByJsPlugin(), svgLoader()],
        resolve: {
            alias: {
                '@': fileURLToPath(new URL('./src', import.meta.url)),
            },
        },
        build: {
            minify: 'terser',
            terserOptions: {
                compress: {
                    drop_console: true,
                    drop_debugger: true,
                },
            },
            lib: {
                entry: resolve(__dirname, 'src/index.ts'),
                name: 'IntegrationPlatformNavbar',
                fileName: 'integration-platform-navbar',
            },
            rollupOptions: {
                // 确保外部化处理那些你不想打包进库的依赖
                external: ['vue', 'element-plus'],
                output: {
                    // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
                    globals: {
                        vue: 'Vue',
                        'element-plus': 'ElementPlus',
                    },
                },
                plugins: [
                    babel({
                        extensions: ['.js', '.ts', '.vue'],
                        babelHelpers: 'runtime',
                        plugins: ['@babel/plugin-transform-runtime'],
                        presets: [
                            [
                                '@babel/preset-env',
                                {
                                    useBuiltIns: false,
                                    targets: {
                                        browsers: ['last 2 versions', '> 1%', 'not ie <= 11'],
                                    },
                                },
                            ],
                        ],
                    }),
                ],
            },
        },
    }

    return config
}

我这样配置后,构建产物里有旧浏览器不支持的语法:

 var createPropertyDescriptor$8 = function createPropertyDescriptor2(bitmap, value) {
    return {
      enumerable: !(bitmap & 1),
      configurable: !(bitmap & 2),
      writable: !(bitmap & 4),
      value
    };
  };

这里的 'value' 在旧浏览器中不兼容,这些代码应该是babel 加入进去的,很奇怪,我使用版本是:

"@babel/plugin-transform-runtime": "^7.23.7",
    "@babel/preset-env": "^7.23.8",
    "@babel/runtime": "^7.23.8",
    "@babel/runtime-corejs3": "^7.23.8",
    "@rollup/plugin-babel": "^5.3.1",
    "vite": "^5.0.11",

你这个配置 polyfill 是运行时的, 如果想要 umd 自带 polyfill, babelHelpers 应该为 bundled,并且去掉 @babel/plugin-transform-runtime

yin-shu commented 8 months ago

it's work for me:这对我有用:

pnpm i -D @babel/plugin-transform-runtime @babel/preset-env @babel/runtime @rollup/plugin-babel
// vite.config.ts
import { fileURLToPath, URL } from 'node:url'
import { resolve } from 'path'
import type { ConfigEnv, UserConfigExport } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import svgLoader from 'vite-svg-loader'
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
import babel from '@rollup/plugin-babel'

export default ({ command, mode }: ConfigEnv): UserConfigExport => {
    const config: UserConfigExport = {
        plugins: [vue(), vueJsx(), cssInjectedByJsPlugin(), svgLoader()],
        resolve: {
            alias: {
                '@': fileURLToPath(new URL('./src', import.meta.url)),
            },
        },
        build: {
            minify: 'terser',
            terserOptions: {
                compress: {
                    drop_console: true,
                    drop_debugger: true,
                },
            },
            lib: {
                entry: resolve(__dirname, 'src/index.ts'),
                name: 'IntegrationPlatformNavbar',
                fileName: 'integration-platform-navbar',
            },
            rollupOptions: {
                // 确保外部化处理那些你不想打包进库的依赖
                external: ['vue', 'element-plus'],
                output: {
                    // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
                    globals: {
                        vue: 'Vue',
                        'element-plus': 'ElementPlus',
                    },
                },
                plugins: [
                    babel({
                        extensions: ['.js', '.ts', '.vue'],
                        babelHelpers: 'runtime',
                        plugins: ['@babel/plugin-transform-runtime'],
                        presets: [
                            [
                                '@babel/preset-env',
                                {
                                    useBuiltIns: false,
                                    targets: {
                                        browsers: ['last 2 versions', '> 1%', 'not ie <= 11'],
                                    },
                                },
                            ],
                        ],
                    }),
                ],
            },
        },
    }

    return config
}

我这样配置后,构建产物里有旧浏览器不支持的语法:

 var createPropertyDescriptor$8 = function createPropertyDescriptor2(bitmap, value) {
    return {
      enumerable: !(bitmap & 1),
      configurable: !(bitmap & 2),
      writable: !(bitmap & 4),
      value
    };
  };

这里的 'value' 在旧浏览器中不兼容,这些代码应该是babel 加入进去的,很奇怪,我使用版本是:

"@babel/plugin-transform-runtime": "^7.23.7",
    "@babel/preset-env": "^7.23.8",
    "@babel/runtime": "^7.23.8",
    "@babel/runtime-corejs3": "^7.23.8",
    "@rollup/plugin-babel": "^5.3.1",
    "vite": "^5.0.11",

你这个配置 polyfill 是运行时的, 如果想要 umd 自带 polyfill, babelHelpers 应该为 bundled,并且去掉 @babel/plugin-transform-runtime

我这样改了,构建产物里还是有 { value, } 的代码,这里有个在线实例可验证, 希望能帮我看下怎么调整: https://stackblitz.com/edit/vitejs-vite-fip7pv?file=vite.config.ts

在 dist/vite-ts.umd.js 里 410 行可以看到

yoyo837 commented 8 months ago

@yin-shu 我这编译没有这个问题,但是我这是直接rollup的。你提供的链接我空了再看看。 image

yin-shu commented 8 months ago

我测试直接用rollup没问题,但在vite中使用不行

thjjames commented 7 months ago

The following method should solve the problem, e.g:

// vite.config.js (e.g)
const { getBabelOutputPlugin } = require('@rollup/plugin-babel');

export default {
  build: {
    rollupOptions: {
      plugins: [
        /**
         * Running Babel on the generated code:
         *  https://github.com/rollup/plugins/blob/master/packages/babel/README.md#running-babel-on-the-generated-code
         *
         * Transforming ES6+ syntax to ES5 is not supported yet, there are two ways to do:
         *  https://github.com/evanw/esbuild/issues/1010#issuecomment-803865232
         * We choose to run Babel on the output files after esbuild.
         *
         * @vitejs/plugin-legacy does not support library mode:
         *  https://github.com/vitejs/vite/issues/1639
         */
        getBabelOutputPlugin({
          allowAllFormats: true,
          presets: [
            [
              '@babel/preset-env',
              {
                useBuiltIns: false, // Default:false
                // Exclude transforms that make all code slower
                exclude: ['transform-typeof-symbol'],
                // https://babeljs.io/docs/en/babel-preset-env#modules
                modules: false,
              },
            ],
          ],
          plugins: [
            /**
             * Extract the helper function.
             */
            [
              '@babel/plugin-transform-runtime',
              {
                corejs: false,
                // version: require('@babel/runtime').version,
              },
            ],
          ],
        }),
      ],
    },
  },
};

Running babel on the generated code by esbuild (vite).

The presets and plugins configuration of babel is only suitable for me, you can modify it.

in lib mode, code is generated by rollup & rollup-plugin-typescript other than esbuild when 'vite build' exec

djkloop commented 4 months ago

我测试直接用rollup没问题,但在vite中使用不行

// 直接这样试一试,把那些多余的rollup插件去掉
{
    build: {
        target: ["es2015"]
    }
}
mikaelkarlsson-se commented 3 days ago

When I use useBuiltIns:"useage",It can't run......

You will likely need to install core-js separately, see https://babeljs.io/docs/babel-preset-env#usebuiltins