最近项目中须要提供一个封装的JS SDK,虽然目前是一个很简单的功能,可是为了往后便于维护,扩展,所以仍是选用了 webpack 做为打包工具,做为参考,推荐一篇上好的文章,感兴趣的朋友能够先阅读一下javascript
JavaScript SDK Design Guide (中文翻译: JavaScript SDK设计指南 )html
做为一个SDK,我想达到以下的目的vue
接下来一步步讲一下如何经过 webpack 实现java
假如咱们最后须要提供的 SDK 以下node
// 引用
<script type="text/javascript" src="http://xxx.com/sdk.js"></script>
// 使用
window.SDK.Shop.getList() // 获取门店信息列表
window.SDK.Store.getById() // 经过ID获取商品信息
复制代码
那么文件列表应该大体以下webpack
|
| - package.json
| - webpack.config.js
| - node_modules
| - src
| - index.js
| - lib
| - shop.js
| - store.js
| - dist
| - build.js
复制代码
webpack 经过 index.js 入口打包好文件,放到 dist 文件夹,一些关键文件的代码应该以下git
webpack.config.jsgithub
let path = require('path')
let webpack = require('webpack')
module.exports = {
entry: {
'sdk': ['./src/index.js']
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
// 压缩混淆 js
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
sourceMap: true
})
]
}
复制代码
shop.jsweb
module.exports = {
getList: function () {
.....
}
}
复制代码
store.jsajax
module.exports = {
getById: function (id) {
.....
}
}
复制代码
index.js
var Shop = require('./lib/shop.js')
var Store = require('./lib/store.js')
module.exports = {
Shop: Shop,
Store: Store
}
复制代码
build.js
// 这里简单的 copy 了 vue-cli 提供的 build 代码
let webpackConfig = require('./webpack.config')
let rm = require('rimraf')
let path = require('path')
let webpack = require('webpack')
let util = require('util')
const compileCallback = (er, stats) => {
if (er) throw er
stats = util.isArray(stats.stats) ? stats.stats : [stats]
stats.forEach((item) => {
process.stdout.write(item.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n')
})
console.log('Build complete.\n')
}
rm(path.resolve(__dirname, './dist'), err => {
if (err) throw err
let compiler = webpack(webpackConfig)
compiler.run(compileCallback)
})
复制代码
这部分很好实现
最简单的作法是在 index.js 里加一句 window.SDK = ...
不过 webpack 有更好的解决方案 output.library
output
选项主要用于配置文件输出规则,而 output.library
选项能够用于输出时将文件暴露为一个变量,能够说是为了打包 SDK 文件而生的一个配置项
这里还有一个 webpack 的教程来帮你如何使用
library
建立 Library
另外一个选项 output.libraryTarget
则能够配置如何输出变量,默认值是 var
简单的说明一下这些值的含义
- var:在当前做用域导出一个变量
- assign: 导出一个变量做为全局变量
- this: 导出做为
this
的一个属性,这个this
不必定是window
,要看引用 SDK 的位置- window: 导出为
window
的一个属性,基本上就算全局变量了- global:导出为
global
的一个属性,估计是这个变量名比较经常使用吧。。- commonjs:导出为
exports
的一个属性,导出的格式能够在 CommonJS 环境里引用- commonjs2:赋值给
module.exports
,一样能够用在 CommonJS 环境里- amd:暴露给 AMD 模块
- umd:暴露为全部模块均可用的格式
- jsonp:包裹到一个 jsonp 包装容器中,也就是一个 Function
所以,咱们稍微修改一下 webpack.config.js 的代码
module.exports = {
...
output: {
path: './dist',
filename: '[name].js',
library: 'SDK',
libraryTarget: "umd"
}
...
}
复制代码
简单的能够写两个 build 脚本,分别打包为压缩代码与未压缩代码,不过 webpack 自己也能够导出为多个配置(这也摸清了 webpack 如何为多个 output
配置不一样的参数)
因而,咱们的 webpack.config.js 代码修改成
module.exports = [
// 未压缩版
{
entry: {
'sdk': './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
library: 'SDK',
libraryTarget: "umd"
}
},
// 压缩版
{
entry: {
'sdk.min': './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
library: 'SDK',
libraryTarget: "umd"
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
sourceMap: true
})
]
}
]
复制代码
打包后的结果以下图所示
这个相对容易点了,能够经过上一条的方式作多个配置,也能够简单的在 entry
中写多个入口
webpack.config.js 代码修改成
module.exports = [
{
entry: {
'sdk': './src/index.js',
'custom': './src/custom.js'
}
...
},
...
]
复制代码
这个就再也不啰嗦了...通过了一系列配置,别说模块了,ES6都能给你加进去,不过要注意的是,若是引入了 babel 或者其余的库,打包出来的 SDK 文件就很大了,甚至是简单的引用一个 webpack-merge 都会增长50K的容量,因此最好仍是以原生的方式去写,若是须要 ajax
等功能就简单的封装一下,能不引用别的库就不引用,若是以为文件体积太大,能够用 webpack-bundle-analyzer 分析一下文件大小的分布,以及是否有重复引用
虽然是个小项目,不过在初期也应该考虑的全面,目前项目虽小,可是不见得之后会发展成什么样,可能有些人会说这么简单的项目用闭包封装一下,暴露两个接口便可,何须搞那么复杂,可是假如以后须要添加新的接口呢,假如须要提供两个 sdk ,分别提供不一样的接口,同时又有部分相同的接口呢,若是这时候再进行重构,会不会对线上有很大的影响?须要进行多少测试?这无形之中给咱们加大了不少成本与不肯定性
但愿这篇比较初级的文章能对你们在建立一个SDK项目上有所帮助~