本文讲讲如何进行地图SDK的开发与编译,以及如何进行ak
的验证以及插件的引用。
新建目录,初始化工程
# 新建目录
mkdir sdk-demo && cd ./sdk-demo
# 初始化工程
npm init -y
创建如下目录和文件
└─config // 配置相关
└─app.js // app配置,主要为启动参数
└─jsdoc.config.js // jsdoc配置文件
└─rollup.config.dev.js // rollup开发配置文件
└─rollup.config.js // rollup配置文件
└─src
└─utils // 工具类
└─file.js // 文件操作工具类
└─lzugis-map.js // SDK主文件
└─app.js // 服务入口文件
修改package.json
文件,并执行命令npm i
安装依赖。
{
...,
"dependencies": {
"express": "~4.16.1",
"live-server": "^1.2.1"
},
"devDependencies": {
"@babel/core": "^7.14.8",
"@babel/preset-env": "^7.14.8",
"@rollup/plugin-commonjs": "^19.0.2",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^13.0.4",
"jsdoc": "^3.6.11",
"rollup": "^2.55.0",
"rollup-obfuscator": "^3.0.1",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-livereload": "^2.0.5",
"rollup-plugin-serve": "^1.1.0",
"rollup-plugin-uglify": "^6.0.4"
}
}
import babel from 'rollup-plugin-babel'
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import serve from 'rollup-plugin-serve'
import livereload from 'rollup-plugin-livereload'
export default {
input: "./src/lzugis-map.js",
output: [
{
file: './dist/lzugis-map.js',
name: 'LzugisMap',
format: 'umd',
sourcemap: false
}
],
plugins: [
serve({
contentBase: 'dist', // 服务器启动的文件夹,默认是项目根目录
port: 18080 // 端口号
}),
livereload('dist'), // 监听dist目录
babel({
exclude: 'node_modules/**'
}),
resolve(),
commonjs()
]
}
开发时文件,在dist
目录下添加index.html
文件,引用lzugis-map.js
,方便开发时调试。
import babel from 'rollup-plugin-babel'
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import { obfuscator } from 'rollup-obfuscator';
import { uglify } from 'rollup-plugin-uglify'
export default {
input: "./src/lzugis-map.js",
output: [
{
file: './dist/lzugis-map.min.js',
name: 'LzugisMap',
format: 'umd',
sourcemap: false
}
],
plugins: [
babel({
exclude: 'node_modules/**'
}),
resolve(),
commonjs(),
obfuscator(),
// js 压缩插件,需要在最后引入
uglify()
]
}
打包时配置文件,将sdk进行压缩和混淆处理。
'use strict'
module.exports = {
'tags': {
'allowUnknownTags': true
},
'source': {
'include': ['./src'],
'includePattern': '.+\\lzugis-map.js',
'excludePattern': '(^|\\/|\\\\)_'
},
'plugins': ['plugins/markdown'],
'recurseDepth': 10,
'templates': {
'cleverLinks': false,
'monospaceLinks': false,
'default': {
'outputSourceFiles': false
}
},
opts: {
// 文档输出路径
destination: './dist/docs',
encoding: 'utf8',
private: true,
recurse: true,
readme: './README-SDK.MD'
}
}
API文档生成配置文件,包括生成路径、使用模板等参数。
package.json
文件,添加执行命令{
...,
"scripts": {
"server:dev": "node ./app.js",
"server": "pm2 start ./app.js",
"lib:dev": "rollup -wc ./config/rollup.config.dev.js",
"lib": "rollup -c ./config/rollup.config.js",
"doc": "./node_modules/.bin/jsdoc -c ./config/jsdoc.config.js"
}
}
为测试功能,修改lzugis-map.js
内容如下:
class LzugisMap {
/**
* @class LzugisMap
* @classdesc lzugis 地图SDK
* @param {Object} [options] - 地图初始化参数
* @param {String | Dom} [options.element = 'map'] - 地图容器
* @param {Number} [options.zoom = 4] - 地图初始化级别
* @param {Array<Number>} [options.center = [0, 0]] - 地图初始化中心点
*/
constructor(options) {
this.options = {
element: 'map',
zoom: 4,
center: [0, 0],
...options
}
}
}
module.exports = LzugisMap
执行命令npm run lib:dev
,修改dist/index.html
文件内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LzugisMap Demo</title>
<style>
.map {
height: 100vh;
}
</style>
</head>
<body>
<div class="map" id="map"></div>
<script src="./lzugis-map.js"></script>
<script>
const map = new LzugisMap({
element: 'map',
zoom: 3,
center: [0, 0]
})
</script>
</body>
</html>
执行命令npm run lib
编译生成SDK,指定命令npm run doc
,编译生成文档。
AK
控制,一方面是为了控制申请了的用户才能使用我们的SDK,另一方面也是为了监控SDK的使用情况。为了能够实现
AK
的监控,一般是由一个对应的“开放平台”或者“AK管控平台”,提供AK
的申请和审核等。其实现逻辑是客户端传入AK
,
服务端进行校验,如果AK
合规,则返回完整的js,如果不合规,则返回错误提示。
插件
的实现是客户端传入需要调用的插件,服务端先进行AK
校验,通过之后再将完整的js和插件的js合城一个js返回给客户端使用。
本文通过node
来实现上述的逻辑,修改app.js
文件如下:
const express = require('express');
const config = require('./config/app')
const fileUtil = require('./src/utils/file')
const liveServer = require("live-server");
const app = express();
// 自定义跨域中间件
const allowCors = function (req, res, next) {
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type');
res.header('Access-Control-Allow-Credentials', 'true');
next();
};
app.use(allowCors);//使用跨域中间件
app.get('/', function (req, res) {
res.redirect('http://localhost:18080/docs/index.html')
})
app.get('/api/map', function (req, res) {
let {ak, plugins} = req.query
plugins = plugins.split(',').filter(v => Boolean(v))
const errorJs = fileUtil.readFile('./dist/error.js')
let sdkJs = fileUtil.readFile(`./dist/lzugis-map.min.js`)
res.type('application/x-javascript;charset=UTF-8');
// AK验证
if(ak !== '844e6d3a9cc34cds398e12fae047d6') {
res.send(errorJs);
} else {
plugins = plugins.split(',')
plugins.forEach(plugin => {
sdkJs += `\r\n/*${plugin} plugin*/\r\n` + fileUtil.readFile(`./dist/plugins/${plugin}.plugin.min.js`)
})
res.send(sdkJs);
}
})
/**
* 接口服务
*/
app.listen(config.api.port, () => {
console.log(`接口已启动,访问地址为:http://${config.api.url}`)
})
/**
* API 服务
*/
liveServer.start({
port: config.doc.port,
host: config.doc.ip,
root: `./dist`,
open: false,
file: "index.html"
});
前端可以通过地址http://localhost:18081/api/map?ak=您申请的ak&plugins=admin进行SDK的调用。
error.js
是一个错误提示文件,其内容如下:
if(window.console&&window.console.error){
window.console.error("<LzugisMap API> Sorry, valid ak required.");
}
通过命令npm run server:dev
可进行开发调试,如需要服务端部署,可借助pm2
进行服务的启动与监控,可运行命令npm run server
。