背景
项目有多个入口文件,没用到cesium的入口文件不需要打包cesium,打包出来的cesium资源需要配合 vite-plugin-compression
插件压缩,使用 vite-plugin-cesium
插件满足不了需求,因此参考 vite-plugin-cesium
改了一个插件出来。
功能
- 在多页面应用中可以指定入口
- 资源可以被压缩
- 支持使用线上的资源
基本思路
- 开发环境:全局设置
CESIUM_BASE_URL
。在configureServer
添加中间件,项目运行中能够通过请求拿到本地的cesium资源。 - 生产环境:全局设置
CESIUM_BASE_URL
。将cesium外部化,不参与构建。如果需要输出文件,就将cesium的必须文件输出到指定目录下面。入口文件添加对Cesium.js
文件的访问。
代码
插件Api
- config:一些基础设置
- configureServer:开发环境设置cesium的中间件
- transformIndexHtml:生产环境生成
Cesium.js
的script标签 - writeBundle:使用这个钩子就可以在压缩cesium之前输出静态资源
参数说明
interface VitePluginCesiumPlusOptions {
devMinifyCesium?: boolean;
/**
* cesium源文件的根路径
* @default "node_modules/cesium/Build"
*/
cesiumBuildRootPath?: string;
/**
* 输出路径
* @default "cesium/"
*/
cesiumOutputPath?: string;
/**
* 指定入口的路径。默认所有入口都打包
*/
inputIndexHtml?: string | string[];
/**
* 线上的Cesium.js链接,如果指定了这个链接,build时就不会输出cesium的源文件了
*/
cesiumJsUrl?: string;
}
代码
import path, { posix } from "path";
import serveStatic from "serve-static";
import externalGlobals from "rollup-plugin-external-globals";
import { copy } from "fs-extra";
const { resolve } = path;
const { join } = posix;
function vitePluginCesiumPlus(options?: VitePluginCesiumPlusOptions) {
let {
devMinifyCesium = false,
cesiumBuildRootPath = "node_modules/cesium/Build",
cesiumOutputPath = "cesium/",
inputIndexHtml,
cesiumJsUrl,
} = options || {};
const cesiumBuildPath = join(cesiumBuildRootPath, "Cesium");
let isBuild = false;
let isOut = false;
let outDir = "";
let CESIUM_BASE_URL = "";
return {
name: "vite-plugin-cesium-plus",
config(config, { command }) {
isBuild = command === "build";
CESIUM_BASE_URL = join(config.base || "/", cesiumOutputPath);
outDir = config.build?.outDir || "dist";
return {
define: {
CESIUM_BASE_URL: JSON.stringify(CESIUM_BASE_URL),
},
build: {
rollupOptions: {
// 外部化
external: ["cesium"],
plugins: [externalGlobals({ cesium: "Cesium" })],
},
},
};
},
configureServer({ middlewares }) {
const cesiumPath = join(
cesiumBuildRootPath,
// 开发环境默认使用未压缩版代码
devMinifyCesium ? "Cesium" : "CesiumUnminified"
);
// 中间件增加对资源请求的访问
middlewares.use(join("/", CESIUM_BASE_URL), serveStatic(cesiumPath));
},
transformIndexHtml(html, { filename }) {
const tags = [];
if (
isBuild &&
// 对入口文件的处理
(typeof inputIndexHtml === "undefined" ||
(typeof inputIndexHtml === "string" &&
resolve(filename) === resolve(inputIndexHtml)) ||
(Array.isArray(inputIndexHtml) &&
inputIndexHtml.map((e) => resolve(e)).includes(resolve(filename))))
) {
isOut = !cesiumJsUrl;
tags.push({
tag: "script",
attrs: {
src: cesiumJsUrl || join(cesiumOutputPath, "Cesium.js"),
},
});
}
return tags;
},
async writeBundle() {
if (isBuild && isOut) {
try {
// 输出静态资源
await Promise.all(
["Assets", "ThirdParty", "Workers", "Widgets", "Cesium.js"].map(
(name) =>
copy(
join(cesiumBuildPath, name),
join(outDir, cesiumOutputPath, name)
)
)
);
} catch (err) {
console.error("copy failed", err);
}
}
},
};
}
export default vitePluginCesiumPlus;
已经将插件发布 vite-plugin-cesium-plus
使用
npm i vite-plugin-cesium-plus -D
基本用法
import { defineConfig } from 'vite'
import cesium from 'vite-plugin-cesium-plus'
export default defineConfig({
plugins: [
cesium()
],
// ...
})
指定入口
import { defineConfig } from 'vite'
import cesium from 'vite-plugin-cesium-plus'
export default defineConfig({
// ...
plugins: [
cesium({
inputIndexHtml: path.resolve(__dirname, 'demo/index.html')
})
],
rollupOptions: {
build: {
input: {
demo: path.resolve(__dirname, 'demo/index.html')
},
// ...
}
}
})
指定线上文件
import { defineConfig } from 'vite'
import cesium from 'vite-plugin-cesium-plus'
export default defineConfig({
// ...
plugins: [
cesium({
cesiumJsUrl: 'https://xxx/Cesium.js'
}),
],
})
注意
插件没有提供对css的引入方式(这样可以按需引入),需要单独引用一下:
import 'cesium/Build/Cesium/Widgets/widgets.css';