vite开发js库,如何build之后只生成一个js文件,并且可以script标签的方式调用?

// package.json
"type": "module",
  "files": [
    "dist",
    "index.d.ts"
  ],
  "main": "./dist/counter.umd.cjs",
  "module": "./dist/counter.js",
  "types": "./index.d.ts",
  "exports": {
    "types": "./index.d.ts",
    "import": "./dist/counter.js",
    "require": "./dist/counter.umd.cjs"
  },

// vite.config.js
export default defineConfig({
  build: {
    lib: {
      entry: './lib/main.js',
      name: 'Counter',
      fileName: 'counter',
    },
  }
})

// lib/main.js
class Counter {
  constructor(options) {
    ...
  }
}
export default Counter

image.png

vite开发js库,run build之后dist生成了两个文件counter.js和counter.umd.cjs,我直接引入<script src="./counter.js" /> 然后console.log(Counter)会报Counter is not defined,但是引用<script src="./dist/counter.umd.cjs" />再console就没有问题是什么原因?
我现在现在的需求是dist只生成一个.js文件,用户既可以通过import引入,也可以通过<script src=”“ /> 方式引入到项目中,该如何实现?
阅读 424
avatarAI BotBETA
### 回答

为了只生成一个 `.js` 文件,并且该文件既可以通过 `import` 引入,也可以通过 `<script>` 标签的方式引入,你需要确保构建的输出是一个 UMD (Universal Module Definition) 格式的文件。UMD 格式的文件可以在各种模块加载环境中工作,包括 CommonJS、AMD 以及作为全局变量。

在你的 `vite.config.js` 文件中,你需要做一些调整来确保只生成一个 UMD 格式的文件。你可以通过设置 `fileName` 和 `formats` 来实现这一点。

修改你的 `vite.config.js` 文件如下:

import { defineConfig } from 'vite';

export default defineConfig({
build: {

lib: {
  entry: './lib/main.js',
  name: 'Counter',
  fileName: (format) => `counter.${format}.js`, // 根据格式生成不同的文件名
  formats: ['umd'] // 只生成 UMD 格式的文件
},
rollupOptions: {
  // 确保外部化依赖(如果有的话),这些依赖不会在构建的输出中包括
  external: [],
  output: {
    // 确保生成的 UMD 文件具有全局变量名 'Counter'
    globals: {
      // 这里可以列出需要外部化的依赖及其全局变量名,如果有的话
    }
  }
}

}
});


在这个配置中,`formats: ['umd']` 确保只生成一个 UMD 格式的文件。`fileName: (format) => `counter.${format}.js`` 允许你根据格式自定义文件名,但在这个例子中,由于我们只生成 UMD 格式,所以文件名将是 `counter.umd.js`。不过,为了符合你的需求(只生成一个 `.js` 文件并且可以通过 `<script>` 标签引入),你可以将 `fileName` 设置为 `'counter.js'`,这样不管格式如何,输出文件名都是 `counter.js`。

fileName: 'counter.js', // 只生成一个名为 counter.js 的文件


这样配置后,运行 `vite build` 将只生成一个 `counter.js` 文件,该文件是一个 UMD 格式的库,可以通过 `<script>` 标签引入,并且全局变量名为 `Counter`。

确保在 HTML 中通过 `<script>` 标签引入时,使用正确的路径,例如:

<script src="./dist/counter.js"></script>
<script>
console.log(Counter); // 现在应该能够正确输出 Counter 类
</script>

这样,你的库就可以通过 <script> 标签直接引入,并且全局可用,同时也支持通过 import 引入。

2 个回答

因为 counter.js 是一个 ES 模块,而 counter.umd.cjs 是一个 UMD 模块。浏览器直接通过 <script> 标签引入时,默认情况下只支持 UMD 或 IIFE 格式的模块,而不支持 ES 模块。

解决思路

修改 package.json
确保 package.json 中的 main 和 module 都指向同一个文件:

{
  "type": "module",
  "files": [
    "dist",
    "index.d.ts"
  ],
  "main": "./dist/counter.js",
  "module": "./dist/counter.js",
  "types": "./index.d.ts",
  "exports": {
    "types": "./index.d.ts",
    "import": "./dist/counter.js",
    "require": "./dist/counter.js"
  }
}

修改 vite.config.js
调整 Vite 的配置来生成一个 UMD 格式的文件,并确保它也支持 ES 模块的导入:

import { defineConfig } from 'vite';

export default defineConfig({
  build: {
    lib: {
      entry: './lib/main.js',
      name: 'Counter',
      formats: ['umd'], // 只生成 UMD 格式
    },
    rollupOptions: {
      output: {
        file: 'dist/counter.js', // 指定输出文件名为 counter.js
        globals: {
          // 如果你的库依赖其他外部库,可以在这里定义全局变量
        },
      },
    },
  },
});


使用方式(有两种)

1.通过 <script> 标签引入:

<script src="./dist/counter.js"></script>
<script>
  console.log(Counter);
</script>

2.通过 ES 模块引入:

import Counter from './dist/counter.js';
console.log(Counter);
推荐问题
宣传栏