原文地址:https://www.jianshu.com/p/85917bcc023f

注意:webpack 和 webpack-cli 的安装参考 https://www.cnblogs.com/mumu122GIS/p/10815777.html  否则容易出错

Cesium 和 Webpack

Webpack是非常强大非常流行的JavaScript 模块打包工具。它可以让开发人员以一种简单直观的 require 方式去加载各种页面需要的文件,极大的方便了开源人员对代码和资源文件进行结构化设计。当编译的时候,它会跟踪代码依赖性,把所有的模型打包到浏览器可以直接加载的一个或者多个bundles中。

在这个教程的前一半,我们创建一个简单的web项目,学会使用webpack,然后再去集成 Cesium npm模块。这是基于Cesium开发正式web项目的很好开端,但是它不是学习Cesium的最简单示例,可以看一下我们的新手入门

在教程的后半部分,我们将讨论更多高级的webpack 配置参数,去优化使用Cesium的项目。

这个优化Cesium和Webpack集成的项目示例,可以查看官网webpack示例 代码库。

先决条件

  • 对命令行,JavaScript语言和web开发需要有一个基本了解。
  • 一个代码编辑器(IDE)。Cesium团队的开发人员都用 Webstorm, 但是 Sublime Text 等工具也可以。
  • 安装了Node.js 。LTS版本最好,但是只要是v6以上都可以的。

创建一个基本的 webpack 程序

第一部分,描述如何建立一个简本的webpack程序以及一个开发测试服务器。如果你已经创建了程序,就想添加Cesium,直接看后面和Cesium继承部分。

使用npm初始化程序

创建一个程序目录,命名为cesium-webpack-app。打开控制台,定位到该目录下,运行下面的命令:

npm init

根据提示信息,填写你的项目里的详细信息。一路按enter使用默认配置也是可以的。完成后,这个目录下创建了一个 package.json文件。

编写自己的程序代码

在这个目录下,创建一个源码目录src。这个目录是我们项目源码所在位置,我们编辑的文件都放这下面。当我们编译后,webpack会自动生成编译后文件放在 dist目录下。
我们创建一个 src/index.html文件,用一个HTML页面的模板。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<title>Hello World!</title>
</head>
<body>
<p>Hello World!</p>
</body>
</html>

现在我们需要添加我们程序的入口 。这个入口会告诉webpack去把所有依赖的源码文件打包。打包后的文件才会在 index.html文件里引用。
现在,为了简单,我们新建 src/index.js文件,只添加下面这句确认环境配置好了。

console.log('Hello World!');

安装和配置webpack

下来我们安装webpack。(再次强调参考文章开头给的webpack 安装链接,否则这一步会报 wbpack 和 webpack-cli 相关错误)

npm install --save-dev webpack
 
webpack安装
配置参数

创建一个名为webpack.config.js的文件。这是定义webpack的配置参数 的地方,它会传给webpack的编译器。

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

首先,我们需要从Nodejs中加载 path和我们刚刚安装的webpack模块。我们告诉webpack,context的及处理路径是Node的全局变量__dirname,这个全局变量指的这个文件所在的目录位置。我们设定了我们的程序入口src/index.js,而且把它命名为app。我们还告诉webpack把打包后的文件(这个文件的名称叫app.js,因为我们设置了程序入口的[name])输出到dist目录下。最后export 把这个配置对象导出,其他文件才能用到这个配置。

加载器(Loaders)

我们还需要加载我们的css以及其他资源文件的方法。webpack允许我们像加载js模块一样,载入这些文件。我们需要使用 loaders。我们需要使用 style-loader, css-loader, 和 url-loader

npm install --save-dev style-loader css-loader url-loader
 
loader安装

继续往 webpack.config.js里添加 module.rules。我们添加两个规则,一个是为css文件,一个是为其他静态文件。每个一个配置,我们定义 test过滤器来筛选这种类似的文件,还定义了一个use数组,指定这种类型用到的loader。

const path = require('path');

const webpack = require('webpack');

module.exports = {
context: __dirname,
entry: {
app: './src/index.js'
},
output: {
filename: '[name].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' ]
}]
}
};
插件

项目已经创建好了,下来需要修改index.html ,让它把打包文件引到页面上。使用webpack的 插件(plugins) 中的 html-webpack-plugin

npm install --save-dev html-webpack-plugin
 
安装plugin

webpack.config.js 文件的最开始加载这个插件,并添加到 plugins配置里去。把 src/index.html 做为一个template设置,webpack就会自动在这个页面注入一个我们的打包文件的引用。

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: '[name].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'
})
]
};

注意,这个配置文件也是一个普通的JavaScript文件,所以我们可以引用任何Nodejs的模块,做任何操作。

打包程序

package.json文件里添加一点脚本配置,我们就能很方便的调用npm。把里面默认的"test"脚本删除掉,我们用不上它。添加一个build命令。

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

这个脚本就是简单的调用了webpack命令,并把我们刚才新建的配置文件webpack.config.js 当作参数传递过去。

因为我们的webpack刚才是本地安装。这样每个项目都使用独立的版本,这也是webpack的推荐安装方式。如果你选择全局安装方式,使用 npm install --global webpack全局安装webpack,然后这里的build命令修改为 webpack --config webpack.config.js
我们运行下编译命令。

npm run build

你应该可以看到webpack开始输出了一些信息:

npm run build

> test-app@1.0.0 build C:\workspace\test-app
> node_modules/.bin/webpack --config webpack.config.js Hash: 2b42bff7a022b5d956a9
Version: webpack 3.6.0
Time: 2002ms
Asset Size Chunks Chunk Names
Assets/Textures/NaturalEarthII/2/0/3.jpg 10.3 kB [emitted]
app.js 162 kB 0 [emitted] app
 
译者机器上的输出
 

我们的打包文件app.jsindex.html 输出到了 dist目录。这些文件已经是可以使用的程序了。

 
编译后的目录

启动开发服务器

这个还不算什么。我们使用 webpack-dev-server 快速的搭建一个开发者服务器,我们的程序就可以实时查看了。
首先安装webpack-dev-server

npm install --save-dev webpack-dev-server

下来,在 package.json文件中增加另外的脚本。使用start命令去启动服务,通过 --config参数传递参数。还传一个 --open去自动在浏览器打开我们的页面。

  "scripts": {
"build": "node_modules/.bin/webpack --config webpack.config.js",
"start": "node_modules/.bin/webpack-dev-server --config webpack.config.js --open"
}

我们需要告诉服务器去哪里寻找文件。这个需要和我们的webpack输出目录一致,也就是 dist目录。所以在 webpack.config.js文件中增加一些配置。

    // 开发服务器配置
devServer: {
contentBase: path.join(__dirname, "dist")
}

最后,我们运行程序

npm start

你应该能看见程序已经在 localhost:8080运行了。如果你打开浏览器控制台,因会看见“Hello World!” 已经输出了。

 
基本webpack程序示例
 
ctrl + c 退出运行 
 

webpack 程序里集成 Cesium

我们的webpack程序已经搭好了框架,下来我们干点有意思的,增加Cesium。

安装Cesium

从npm中安装 cesium 模块,在 package.json 中增加开发依赖选项。

npm install --save-dev cesium

webpack中配置Cesium

Cesium是一个庞大的复杂的库。除了JavaScript模块之外,它还包含静态资源css,图片和json文件。它也包含为了多线程进行大量计算的web worker。和传统npm模块不同,Cesium也没有定义一个入口,因为这个库可以各种方式应用。为了正确使用,我们需要配置一些额外选项。
首先,我们定义Cesium所在位置。我们使用源码,这样我们就可以使用独立模块,依靠webpack可以跟踪依赖性。其他方式是使用编译好的(最小化压缩或者未压缩)版本的Cesium;可是,那些模块已经被RequireJS optimizer 组合和优化,这种方式集成起来简单避免犯错,但是对于我们的优化灵活度不够好。

webpack.config.js,我们增加如下配置

// Cesium源码所在目录
const cesiumSource = 'node_modules/cesium/Source';
const cesiumWorkers = '../Build/Cesium/Workers';

我们选择使用了npm 中的模块,安装容易一些,当然你也可以用 GitHub 库 上的版本,或者解压已发布版本下载。这时候仅仅需要更改cesiumSource 指向Cesium的 Source 目录,相对 webpack.config.js 文件的相对路径。
接着再增加一些配置项,为了解决使用webpack编译Cesium的一些问题。

    output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist'),
//需要编译Cesium中的多行字符串
sourcePrefix: ''
},
amd: {
//允许Cesium兼容 webpack的require方式
toUrlUndefined: true
},
node: {
// 解决fs模块的问题(Resolve node module use of fs)
fs: 'empty'
},

快速过下,为什么这些配置选项需要配置。

  • output.sourcePrefix: '' 因为某些版本的webpack默认会在输出的每一行的开始增加一个\t 字符。Cesium有很多多行字符串,所以我们需要使用空字符串 ''来覆盖这个选项。
  • amd.toUrlUndefined: true 告诉Cesium,webpack中计算 require声明的AMD 模块里的toUrl 函数和标准的不兼容。
  • node.fs: 'empty' 解决一些第三方库使用的fs 模块,它一般是用在NodeJS的环境里,而不能在浏览器环境里使用。
    下来我们增加一个 cesium 别名(alias) ,我们就很容易的在项目里引用,就像一个传统的Node 模块。
    resolve: {
alias: {
// Cesium模块名称
cesium: path.resolve(__dirname, cesiumSource)
}
},

</figure>

管理Cesium 静态文件

最后,我们确认一下Cesium的静态资源,控件,web worker文件能被服务正确加载。
我们使用 copy-webpack-plugin,它能在编译阶段,把Cesium里静态文件整个拷贝到 dist 目录下,确保我们的服务能访问它。首先,安装它。

npm install --save-dev copy-webpack-plugin

下来在webpack.config.js文件最开始require它。

const CopywebpackPlugin = require('copy-webpack-plugin');

此外,在plugins 目录下增加下述配置:

    plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
// 拷贝Cesium 资源、控价、web worker到静态目录
new CopywebpackPlugin([ { from: path.join(cesiumSource, cesiumWorkers), to: 'Workers' } ]),
new CopywebpackPlugin([ { from: path.join(cesiumSource, 'Assets'), to: 'Assets' } ]),
new CopywebpackPlugin([ { from: path.join(cesiumSource, 'Widgets'), to: 'Widgets' } ])
],

我们直接拷贝了AssetsWidgets目录。也拷贝了编译好的 web worker脚本,他们已经使用 RequireJS optimizer编译和优化过了。因为web woker设计就是运行在他们自己的线程里,所以他们可以直接载入和运行。web worker很少需要调试他们原来的代码。所以直接整个从 Build/Cesium/Workers目录拷贝过去。
如果你用的GitHub库的源码,那么这个Build目录不存在。确认你定位到了Cesium的根目录下,然后运行 npm run release去编译输出。更多信息可以查看Cesium编译指导
最后,我们使用DefinePlugin 定义了一个环境变量,这个告诉Cesium加载静态文件的URL根路径,并把它编译到webpack里去。最后plugins 的配置数组应该是这样的:

    plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CopywebpackPlugin([ { from: path.join(cesiumSource, cesiumWorkers), to: 'Workers' } ]),
new CopywebpackPlugin([ { from: path.join(cesiumSource, 'Assets'), to: 'Assets' } ]),
new CopywebpackPlugin([ { from: path.join(cesiumSource, 'Widgets'), to: 'Widgets' } ]),
new webpack.DefinePlugin({
//Cesium载入静态的资源的相对路径
CESIUM_BASE_URL: JSON.stringify('')
})
],

在我们的程序里引用Cesium

现在我们的程序里引用Cesium的独立模块有几种方式。使用CommonJS的语法,以及最新的ES6的 import模块声明。
另外,你也可以通过一个 Cesium 引入整个Cesium库(例如,我们在 Sandcastle中所用的方式)。你也可以只请求某个你需要的特定模块。因为Cesium是一个巨大的库,这种方式让你只引用你用的特定模块,而不是整个Cesium库。

CommonJS 形式的 require

引用Cesium整个库:

var Cesium = require('cesium/Cesium');
var viewer = new Cesium.Viewer('cesiumContainer');

引用某个Cesium库:

var Color = require('cesium/Core/Color');
var color = Color.fromRandom();
ES6 形式的 import

引用Cesium整个库:

import Cesium from 'cesium/Cesium';
var viewer = new Cesium.Viewer('cesiumContainer');

引用某个Cesium库:

import Color from 'cesium/core/Color';
var color = Color.fromRandom();

请求静态资源文件

webpack的设计理念就是每个文件都当作一个模块。所以导入静态资源和导入js模块完全相同。我们已经在loaders里面配置了,告诉webpack每种类型的文件使用哪个loader,所以我们只需要调用 require

require('cesium/Widgets/widgets.css');

Hello World! 示例

有了基本框架也学习如何引入Cesium文件,我们来创建一个简单的Hello World程序。
再看下index.js文件。删除它的内容,首先我们引入 Cesium,然后定义 Cesium的对象:

var Cesium = require('cesium/Cesium');

为了使用Cesium Viewer里的控件,我们还需要引入Cesium的CSS:

require('cesium/Widgets/widgets.css');

因为现在cesium 需要从 cesium ion 获取底图,所以再加下面一行代码(token 需要到 cesium ion 申请),否则cesium 界面的地球出不来:

Cesium.Ion.defaultAccessToken = 'xxxxxx自己的token xxxxxxx';

在HTML的body部分,我们创建了一个viewer需要的div。在 index.html 文件里,删除 <p>Hello World!</p> 这一行,替换成下面:

<div id="cesiumContainer"></div>

最后,我们创建一个viewer的实例。返回到 index.js 文件,添加下面代码:

var viewer = new Cesium.Viewer('cesiumContainer');

最后 index.js 文件的内容为:

var Cesium = require('cesium/Cesium');
require('cesium/Widgets/widgets.css');
Cesium.Ion.defaultAccessToken = 'xxxxxx自己的token xxxxxxx';
var viewer = new Cesium.Viewer('cesiumContainer');

当我们运行 npm start ,我们将看见浏览器里的Cesium控件了。

 
Hello World 程序

为了美观,我们用一些自定义css去掉页面上的白色边界。
创建一个新的文件src/css/main.css,增加下面的样式:

html, body, #cesiumContainer {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}

index.js里require它,在其他require的后面。

require('./css/main.css');

重新npm start,Cesium的控件完美全屏了。

随便拷贝粘贴 Sandcastle 中的示例。 我认为 粒子系统的示例 最能说明问题。

 
示例程序

webpack 高级配置

webpack有很多其他方法增加性能、减小打包大小、执行额外的或者复杂的编译过程。对于使用Cesium库,我们将讨论一些配置选项。
我们的最佳配置选项示例放在github的配置库里 webpack.release.config.js

代码切片

webpack默认会把Cesium和整个程序代码打进一个 chunk中,最终这个库非常庞大。我们也可以用CommonChunksPlugin把Cesium打到它自己的包,提升程序的性能。如果最终你的程序创建了多个chunks,他们可以引用一个通用的cesiumchunk。
只需要在 webpack.config.js添加这个插件,然后设置打断Cesium模块的规则。

    plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'cesium',
minChunks: module => module.context && module.context.indexOf('cesium') !== -1
})
]

这个插件最新版webpack上已经不能这么配置了,使用config.optimization.splitChunks去设置,详情点击webpack-splitChunks

启用 source maps

Source maps 允许webpack跟踪原来代码中的错误,它有很多配置项。它用编译速度来换取或多或少的调试详情信息。我们推荐使用'eval'选项,但是尽量使用你自己开发中最好的方式。

    devtool: 'eval'

不推荐在最终产品代码里添加Source maps(容易被破解呗)。

删除 pragmas

Cesium源码里包含了一些开发错误和警告信息,但是产品中是不需要的。通常我们使用 RequireJS Optimizer在release编译下压缩它。因为没有webpack内置的方式去删除这些警告,我们将使用 strip-pragma-loader
首先,安装。

npm install strip-pragma-loader --save-dev

然后在loader的 module.rules增加规则,并且 把 debug 设置为 false.

    rules: [{
// 删除 cesium pragmas
test: /\.js$/,
enforce: 'pre',
include: path.resolve(__dirname, cesiumSource),
use: [{
loader: 'strip-pragma-loader',
options: {
pragmas: {
debug: false
}
}
}]
}]

混淆和压缩

混淆和压缩代码使最终产品的代码变得更小。对于一个release编译,Cesium会JavaScript文件,并且压缩CSS文件。为了混淆Cesium源码,我们使用 uglifyjs-webpack-plugin插件。

npm install uglifyjs-webpack-plugin --save-dev

引入这个插件

const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

在插件里引用它

    plugins: [
new webpack.optimize.UglifyJsPlugin()
]

这个插件最新版webpack上已经不能这么配置了,使用config.optimization.minimize去设置,详情点击webpack-optimization
为了压缩css代码,在css-loader中使用minimize选项。

    module: {
rules: [{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
// minify loaded css
minimize: true
}
}
]
}]
}

相关资源

官方 cesium-webpack-示例的git库。包含最小的webpack配置,以及此篇教程的hello word代码,还有部分可选的代码配置选项。

学习如何基于Cesium开发项目实例,比如如何添加数据和配置样式,那么去学习 Cesium Workshop 教程

玩下 Sandcastle以及官方用户手册

深入学习webpack,可以看下webpack 概念,或者看下webpack的配置手册

 

转:Cesium 和 Webpack的更多相关文章

  1. Cesium官方教程13--Cesium和Webpack

    原文地址:https://cesiumjs.org/tutorials/cesium-and-webpack/ Cesium 和 Webpack Webpack是非常强大非常流行的JavaScript ...

  2. 一步步建立 Vue + Cesium 初始化项目

    一步步建立 Vue + Cesium 初始化项目 初始化 Vue 项目 升级 npm npm install -g npm 安装 @vue/cli 和 @vue/cli-service-global ...

  3. Cesium Vue开发环境搭建

    最近被问到如何在 vuejs 中集成 cesium,首先想到的官网应该有教程.官网有专门讲 Cesium and Webpack(有坑),按照官网的说明,动手建了一个Demo,在这记录下踩坑过程. 一 ...

  4. 关于Cesium 官方教程

    最近一直在准备第一次QQ群的Cesium基础培训公开课,虽说使用Cesium也有段日子了,但是要说对Cesium了解有多深,还真不一定.原因是一直以来我都是用哪里学哪里.基于多年开发三维数字地球的底层 ...

  5. cesium-webpack 入门开发系列一初探篇(附源码下载)

    前言 cesium-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址 we ...

  6. vue+cesiumjs的环境搭建【script引入】

    [可以看我的博客里另外一篇----- import引入 ,可以不用script引入] 最近做项目要用到cesium,然后参照网上的一些步骤,最后发现报错了,其中有两种错比较多: ①  This dep ...

  7. Ceisum官方教程2 -- 项目实例(workshop)

    原文地址:https://cesiumjs.org/tutorials/Cesium-Workshop/ 概述 我们很高兴欢迎你加入Cesium社区!为了让你能基于Cesium开发自己的3d 地图项目 ...

  8. Cesium中级教程10 - CesiumJS and webpack

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ webpack是打包JavaScript模块流行且强大的工具.它 ...

  9. react 地图发布 cesium 篇

    上篇文章介绍了如何搭建 react cesium 开发环境.在开发环境下,项目一切运行正常.最近把项目打包发布出来,却遇见了 cesium 不能正确初始化.打开浏览器的调试面板,出现好多 404,资源 ...

随机推荐

  1. avalon怎么让重叠的图片改变显示层级?

    <span style="display: inline-block;width:20%;"> <span style="display: inline ...

  2. OpenFOAM清理计算结果(只保留原始的0,system,constant)

    原视频下载地址:https://yunpan.cn/cMpyLZq8sWQgq(提取码:a08b)

  3. js函数运行方式一览

    定义对象然后调用 j = {} j["delete"]=function () { console.log("ok") } j["delete&quo ...

  4. 【多线程与并发】Java并发工具类

    主要有两类 ①并发流程控制相关:CountDownLatch.CyclicBarrier.Semaphore ②线程间交换数据相关:Exchanger: CountDownLatch 作用:允许一个或 ...

  5. HTMLPage测试js通过ajax调用

    HTMLPage测试js通过ajax调用接口 <!DOCTYPE html> <html lang="en" xmlns="http://www.w3. ...

  6. 使用OpenCV(C ++ / Python)进行人脸交换

    -- 图3.面部对齐.左:检测到面部标志和凸包.中:凸包上的点的Delaunay三角剖分.右:通过仿射扭曲三角形进行面部对齐. 1 人脸对齐 1.1 脸部地标检测 两个脸部的几何形状非常不同,因此我们 ...

  7. Vehicle routing with Optaplanner graph-theory

    Vehicle routing with Optaplanner - Stack Overflow https://stackoverflow.com/questions/22285252/vehic ...

  8. mount: unknown filesystem type ‘ntfs’ 解决方法

    问题: mount –t ntfs /dev/sde1 /mnt/mount: unknown filesystem type ‘ntfs’ 这是由于CentOS release 6.6(Final) ...

  9. CSS清除浮动方法集合

    CSS清除浮动方法集合 一.浮动产生原因   -   TOP 一般浮动是什么情况呢?一般是一个盒子里使用了CSS float浮动属性,导致父级对象盒子不能被撑开,这样CSS float浮动就产生了. ...

  10. ES6深入浅出-3 三个点运算 & 新版字符串-1.函数与对象的语法糖

    主要讲的内容 时间充裕的话就讲,模板字面量 默认参数值 首先讲es6之前,我们是怎么做的.例如我们要写一个求和的函数, 请两个参数的和,但是如果有的人就是穿一个参数呢? 那么b没有传值,b的值是多少呢 ...