CesiumJS 与 Webpack 指南

327 阅读7分钟

原文地址:github.com/CesiumGS/ce…

Webpack 是一个颇受欢迎且功能强大的JavaScript模块打包工具。它允许开发者以一种直观的方式来构建代码和资源,并能够根据需要使用简单的 require 语句来加载不同类型的文件。在构建过程中,Webpack 会追踪代码之间的依赖关系,并将它们打包成一个或多个由 Web 浏览器加载的包。如果想利用 CesiumJS 开发更加高级的 Web 应用,本教程将是个不错的起点。如果是刚开始接触 Cesium 并且想学习构建您的第一个样例应用,请查看我们的入门教程

在本教程中,您将学习到:

  • 如何从零开始使用Webpack构建一个简易的Web应用;
  • 如何将Cesium npm包集成到你的Web应用中。

前提条件

  • 对命令行、JavaScript 和 Web 开发有基本的了解;
  • 计算机中已安装 Node.js。建议使用最新的LTS版本。

通过 npm 初始化应用

  1. 创建一个新的目录来存放您的应用程序。
  2. 打开 terminal(控制台窗口)并导航至该目录。
  3. 执行 npm init 命令,并按照提示输入应用程序相关信息。如果某些提示您不确定如何回答,直接按 Enter 键接受默认值即可。您可以随时修改 npm init 创建的 package.json 文件中的信息。

编写应用程序代码

  1. 创建一个名为 src 的目录来放置您的应用代码。在构建应用时,Webpack 会自动在一个名为 dist 的目录中生成打包后的文件。
  2. 在步骤1所创建的 src 目录中,新建 index.htmlindex.js 文件。
  3. src/index.html 中添加以下代码,作为我们起步的HTML页面模板:
    <!doctype html>
    <html>
      <head>
        <meta charset="utf-8" />
      </head>
      <body>
        <p>你好,世界!</p>
      </body>
    </html>
    
  4. src/index.js 中添加以下内容,作为起始的JavaScript代码模板:
    console.log("Hello World!");
    
  5. 创建一个 src/css/main.css 文件,并添加以下CSS代码:
    html,
    body,
    #cesiumContainer {
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
      overflow: hidden;
    }
    

安装和配置Webpack

  1. 通过执行 npm install --save-dev webpack 命令来安装 Webpack。这将在您的主目录中生成 package-lock.jsonpackage.json 文件。同时,您的主目录中还会多出一个名为 node_modules 的新文件夹。

  2. 在主目录中新建一个 webpack.config.js 文件。

  3. 通过在 webpack.config.js 中加入以下代码来定义Webpack配置对象:

    const path = require("path");
    const webpack = require("webpack");
    module.exports = {
      context: __dirname,
      entry: {
        app: "./src/index.js",
      },
      output: {
        filename: "app.js",
        path: path.resolve(__dirname, "dist"),
      },
    };
    

    以上代码中 context 指定了文件的基本路径;entry 用来定义入口,其中src/index.js 是我们的入口文件。Webpack将会输出名为 app.js 的打包文件到运行时创建的 dist 文件夹中。

  4. Webpack 将所有资源视作模块进行加载。通过使用 loaders 我们可以加载 CSS 和其他资源文件。运行 npm install --save-dev style-loader css-loader url-loader 命令来安装 style-loadercss-loaderurl-loader。根据需要,您还可以安装任何未来可能用到的其他loader。这些loader可以在整个过程中的任何时刻被安装。

  5. 更新 webpack.config.js,向其中添加两个 module.rules 规则。第一个规则用于处理CSS文件,第二个规则用于管理其他静态文件。为每个规则定义一个 test 参数来指定需要加载的文件类型,以及一个 use 列表来指定使用的 loader。更新后的 webpack.config.js 应该如下所示:

    const path = require("path");
    const webpack = require("webpack");
    module.exports = {
      context: __dirname,
      entry: {
        app: "./src/index.js",
      },
      output: {
        filename: "app.js",
        path: path.resolve(__dirname, "dist"),
      },
      module: {
        rules: [
          {
            test: /\.css$/,
            use: ["style-loader", "css-loader"],
          },
          {
            test: /\.(png|gif|jpg|jpeg|svg|xml|json)$/,
            use: ["url-loader"],
          },
        ],
      },
    };
    
  6. 若要将 index.html 定义为模板,并将我们的打包文件注入该页面,需要使用一个名为 html-webpack-plugin 的Webpack插件。使用命令 npm install --save-dev html-webpack-plugin 来安装这个插件。

  7. webpack.config.jsplugins 部分引入 html-webpack-plugin,并将 src/index.html 设为模板。最后,在 webpack.config.js 中添加 mode: 'development' 来指定Webpack的模式为开发模式。此时的 webpack.config.js 看起来应该像这样:

    const path = require("path");
    const webpack = require("webpack");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    module.exports = {
      context: __dirname,
      entry: {
        app: "./src/index.js",
      },
      output: {
        filename: "app.js",
        path: path.resolve(__dirname, "dist"),
      },
      module: {
        rules: [
          {
            test: /\.css$/,
            use: ["style-loader", "css-loader"],
          },
          {
            test: /\.(png|gif|jpg|jpeg|svg|xml|json)$/,
            use: ["url-loader"],
          },
        ],
      },
      plugins: [
        new HtmlWebpackPlugin({
          template: "src/index.html",
        }),
      ],
      mode: "development",
    };
    

打包应用程序

  1. 在项目的 package.json 文件中定义可以通过 npm 运行的脚本命令,这里需要添加一个用于构建项目的 build 命令:

    "scripts": {
        "build": "node_modules/.bin/webpack --config webpack.config.js"
    }
    

    完成后,您的 package.json 文件应该如下所示:

    {
     "name": "cesiumjs-webpack-tutorial",
     "version": "1.0.0",
     "description": "",
     "main": "index.js",
     "scripts": {
       "build": "node_modules/.bin/webpack --config webpack.config.js"
     },
     "author": "",
     "license": "ISC",
     "devDependencies": {
       "css-loader": "^6.2.0",
       "html-webpack-plugin": "^5.3.2",
       "style-loader": "^3.2.1",
       "url-loader": "^4.1.1",
       "webpack": "^5.50.0"
     }
    }
    

    请注意,本文件的具体内容会根据您在 通过 npm 初始化应用 中第3步所做的选择而有所不同。

  2. 运行命令 npm run build。如需安装 Webpack CLI,请使用命令 npm install --save-dev webpack-cli

  3. 如果没有错误,您的输出应类似于以下内容:

    $ npm run build
       > cesiumjs-webpack-tutorial@1.0.0 build
       > node_modules/.bin/webpack --config webpack.config.js
       asset app.js 1.22 KiB [emitted] (name: app)
       asset index.html 376 bytes [emitted]
       ./src/index.js 28 bytes [built] [code generated]
       webpack 5.50.0 compiled successfully in 86 ms
    

    请确认 app.jsindex.html 文件已被添加到 dist 文件夹中。

运行开发服务器

  1. 为了提供开发构建并预览应用,您可以使用 webpack-dev-server 。首先,通过运行 npm install --save-dev webpack-dev-server 来安装它。

  2. 接着,在 package.json 文件中新增一个 start 脚本来运行开发服务器。注意,需要通过 --config 标志指定配置文件,同时使用 --open 标志来确保执行命令后浏览器会自动打开应用。更新后的 package.json 应如下所示:

    {
      "name": "cesiumjs-webpack-tutorial",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "build": "node_modules/.bin/webpack --config webpack.config.js",
        "start": "node_modules/.bin/webpack serve --config webpack.config.js --open"
      },
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "css-loader": "^6.2.0",
        "html-webpack-plugin": "^5.3.2",
        "style-loader": "^3.2.1",
        "url-loader": "^4.1.1",
        "webpack": "^5.50.0",
        "webpack-cli": "^4.7.2",
        "webpack-dev-server": "^3.11.2"
      }
    }
    
  3. 执行 npm start 后,浏览器会自动打开 http://localhost:8080/,您应该能看到一个渲染了 "你好,世界!" 的页面。

image.png

将 CesiumJS 集成到 Webpack 应用中

CesiumJS 是一个功能强大的开源 JavaScript 库,专为构建 3D 地球和地图而设计。它的功能复杂且内容丰富,不仅包含 JavaScript 模块,还包含了CSS、图像、json 文件等多种静态资源。此外,CesiumJS 还引入了Web Worker,以支持在不同线程中处理计算密集型任务。与传统的 npm 模块相比,CesiumJS 没有设置一个明确的 entry(入口),因此,在利用 webpack 进行项目构建时,您需要进行一些额外的配置。

首先,需要明确指出 CesiumJS 的位置。本教程通过源代码的方式引入 Cesium,这样 webpack 就可以识别库中包含的模块,并追踪它们之间的依赖关系。当然,您也可以使用 CesiumJS 的构建版本(已压缩或未压缩)。但需要注意的是,已构建的模块是预先打包和优化过的,这可能会在一定程度上限制您的灵活使用。

安装CesiumJS

  1. 通过命令 npm install --save-dev cesium 安装Cesium模块。
  2. 更新您的 webpack.config.js 来解决 CesiumJS 与 webpack 使用的 AMD 不兼容的问题,并添加一个 cesium 别名以便在应用程序代码中引用它。添加这些更改后,webpack.config.js 应如下所示:
    // CesiumJS源码的路径
    const cesiumSource = "node_modules/cesium/Source";
    const cesiumWorkers = "../Build/Cesium/Workers";
    const path = require("path");
    const webpack = require("webpack");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    module.exports = {
      context: __dirname,
      entry: {
        app: "./src/index.js",
      },
      output: {
        filename: "app.js",
        path: path.resolve(__dirname, "dist"),
        // 编译Cesium中多行字符串所需
        sourcePrefix: '',
      },
      amd: {
        // 允许webpack友好地使用Cesium中的require
        toUrlUndefined: true,
      },
      resolve: {
        alias: {
          cesium: path.resolve(__dirname, cesiumSource),
        },
        mainFiles: ['index', 'Cesium'],
      },
      module: {
        rules: [
          {
            test: /\.css$/,
            use: ["style-loader", "css-loader"],
          },
          {
            test: /\.(png|gif|jpg|jpeg|svg|xml|json)$/,
            use: ["url-loader"],
          },
        ],
      },
      plugins: [
        new HtmlWebpackPlugin({
          template: "src/index.html",
        }),
      ],
      mode: "development",
    };
    

管理 CesiumJS 静态文件

为了确保 CesiumJS 的静态资源、Widgets 和 Web Worker 文件能正确加载,您需要使用 copy-webpack-plugin 将这些静态文件复制到 dist 目录中。

首先,通过运行 npm install --save-dev copy-webpack-plugin 安装插件。随后,您需要在 webpack.config.js 中配置该插件,以确保 Cesium 的 Assets、Widgets 和 Workers 被正确复制到 dist 目录中。更新后的webpack.config.js应该如下所示:

// CesiumJS源代码的路径
const cesiumSource = "node_modules/cesium/Source";
const cesiumWorkers = "../Build/Cesium/Workers";
const CopyWebpackPlugin = require("copy-webpack-plugin");
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
  context: __dirname,
  entry: {
    app: "./src/index.js",
  },
  output: {
    filename: "app.js",
    path: path.resolve(__dirname, "dist"),
    sourcePrefix: "",
  },
  amd: {
    // 使webpack能够以友好的方式使用Cesium中的require
    toUrlUndefined: true,
  },
  resolve: {
    alias: {
      cesium: path.resolve(__dirname, cesiumSource),
    },
    mainFiles: ["index", "Cesium"],
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.(png|gif|jpg|jpeg|svg|xml|json)$/,
        use: ["url-loader"],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "src/index.html",
    }),
    // 将Cesium的Assets、Widgets和Workers复制到一个静态目录
    new CopyWebpackPlugin({
      patterns: [
        { from: path.join(cesiumSource, cesiumWorkers), to: "Workers" },
        { from: path.join(cesiumSource, "Assets"), to: "Assets" },
        { from: path.join(cesiumSource, "Widgets"), to: "Widgets" },
      ],
    }),
    new webpack.DefinePlugin({
      // 在cesium中定义相对的基路径用于加载资源
      CESIUM_BASE_URL: JSON.stringify(""),
    }),
  ],
  mode: "development",
};

将 CesiumJS 集成到应用中

  1. 更新您的 index.js 来启动 CesiumJS,如初始化视图器、添加地形、创建 OSM Buildings 和定位相机至特定位置等。

    import {
      Ion,
      Viewer,
      Terrain,
      createOsmBuildingsAsync,
      Cartesian3,
      Math,
    } from "cesium";
    import "cesium/Widgets/widgets.css";
    import "../src/css/main.css";
    // 你的访问令牌可以在 https://cesium.com/ion/tokens 找到。
    // Ion.defaultAccessToken = "你的令牌在这里";
    // 在ID为`cesiumContainer`的HTML元素中初始化Cesium Viewer。
    const viewer = new Viewer("cesiumContainer", {
      terrain: Terrain.fromWorldTerrain(),
    });
    // 添加Cesium OSM Buildings,一个全球性的3D建筑层。
    const buildingTileset = await createOsmBuildingsAsync();
    viewer.scene.primitives.add(buildingTileset);
    // 将相机飞向给定经纬度和高度的旧金山。
    viewer.camera.flyTo({
      destination: Cartesian3.fromDegrees(-122.4175, 37.655, 400),
      orientation: {
        heading: Math.toRadians(0.0),
        pitch: Math.toRadians(-15.0),
      },
    });
    

    上述代码演示了如何利用 CesiumJS 创建一个场景,在地形上添加Cesium OSM Buildings,并将视图定位至旧金山。

  2. 更新 index.html,添加 CesiumContainer

    <!doctype html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
      </head>
      <body>
        <div id="cesiumContainer"></div>
      </body>
    </html>
    
  3. 运行 npm run build,确保项目被正确构建。

  4. 使用 npm start 运行您的应用,并在浏览器中打开 http://localhost:8080/ 查看集成了 CesiumJS 的效果。

image.png

您可以随意复制并粘贴您最喜爱的Sandcastle示例。例如,许多社区成员都喜欢的Cesium OSM Buildings演示。

高级 Webpack 配置及其他资源

Webpack 是一个强大的模块打包工具,它提供了一系列高级功能,可帮助提升应用的性能,减小包的体积,并实现复杂的构建过程。在此部分,我们将专门讨论一些与集成 CesiumJS 库时相关的高级配置选项。

启用 Source Maps

源映射(Source Maps)功能允许 Webpack 追溯编译后的代码中的错误和警告到其原始源代码,为开发者提供了丰富的调试信息。要在开发过程中充分利用这项功能以提高调试效率,我们推荐在 webpack.config.js 文件中将 devtool 选项设置为 eval。这项设置可以加快编译速度并优化开发体验:

devtool: 'eval'

然而,请注意,在生产环境中慎用源映射,以避免潜在的性能影响及安全问题。

其他资源

Cesium 官方提供的 cesium-webpack-example 仓库包含了对于初学者而言的最小 Webpack 配置以及本教程所涉及的基础代码示例。

您可以通过 CesiumJS 教程 来深入学习 CesiumJS 的各种功能和使用方式。此外,强烈推荐您探索 Sandcastle 示例库,它提供了丰富的案例,帮助您理解并掌握 CesiumJS 在实际应用中的强大能力。

如果您想进一步掌握 Webpack 的细节与高级特性,请参阅 Webpack 官方入门指南,这是学习基础知识的绝佳起点。对于那些希望深入理解其强大功能的用户来说,Webpack 的 API 文档 提供了详尽的信息和指引。