diff --git a/publish/build.cmd b/publish/build.cmd
new file mode 100644
index 0000000000000000000000000000000000000000..359cf711ace5cbfb37e07082809e4623f73ff34a
--- /dev/null
+++ b/publish/build.cmd
@@ -0,0 +1,2 @@
+cd ../form & npm install & npm run publish & cd ../play & CocosCreator.exe --path "./" --build "platform=web-desktop;debug=true" --force & cd ../publish & node build.js
+pause
diff --git a/publish/build.js b/publish/build.js
new file mode 100644
index 0000000000000000000000000000000000000000..670f7c73ae517c4eae995c16cadc43b1167e0750
--- /dev/null
+++ b/publish/build.js
@@ -0,0 +1,85 @@
+let fs = require('fs');
+const compressing = require('compressing');
+
+function fix2(num) {
+    if (num >= 10) {
+        return '' + num;
+    } else {
+        return '0' + num;
+    }
+}
+
+async function copyDir(src, dst) {
+    const exists = await fs.existsSync(dst);
+    if (!exists) {
+        await fs.mkdirSync(dst);
+    }
+    //读取目录
+    const paths = await fs.readdirSync(src);
+    for (let i = 0; i < paths.length; i++) {
+        let path = paths[i];
+        const newSrc = `${src}/${path}`;
+        const newDst = `${dst}/${path}`;
+        const st = await fs.statSync(newSrc);
+        if (st.isFile()) {
+            console.log('copy: ' + newDst);
+            const data = await fs.readFileSync(newSrc);
+            await fs.writeFileSync(newDst, data);
+        } else if (st.isDirectory()) {
+            copyDir(newSrc, newDst);
+        }
+    }
+}
+
+async function removeDir(src) {
+    const exists = await fs.existsSync(src);
+    if (!exists) {
+        return;
+    }
+
+    //读取目录
+    const st = await fs.statSync(src);
+    console.log(st);
+    const paths = await fs.readdirSync(src);
+    for (let i = 0; i < paths.length; i++) {
+        let path = paths[i];
+        const newSrc = `${src}/${path}`;
+        const st = await fs.statSync(newSrc);
+        if (st.isFile()) {
+            console.log('remove: ' + newSrc);
+            await fs.unlinkSync(newSrc);
+        } else if (st.isDirectory()) {
+            await removeDir(newSrc);
+        }
+    }
+    await fs.rmdirSync(src);
+}
+
+async function main() {
+    let date = new Date();
+    let fileName = `Release_${date.getFullYear()}${fix2(date.getMonth() + 1)}${fix2(date.getDate())} `;
+    fileName += `${fix2(date.getHours())}-${fix2(date.getMinutes())}-${fix2(date.getSeconds())}`;
+
+    await removeDir('./publish/play');
+    await removeDir('./publish/form');
+
+    await copyDir('../play/build/web-desktop', './publish/play');
+
+    const data = await fs.readFileSync('./index.html');
+    await fs.writeFileSync('./publish/play/index.html', data);
+
+    compressing.zip.uncompress('../form/publish/form.zip', './publish/form')
+        .then(() => {
+            const tarStream = new compressing.zip.Stream();
+            tarStream.addEntry('./publish/play');
+            tarStream.addEntry('./publish/form');
+
+            const destStream = fs.createWriteStream(`publish/${fileName}.zip`);
+
+            tarStream.pipe(destStream);
+
+            console.log('打包完成!');
+        });
+}
+
+main();
\ No newline at end of file
diff --git a/publish/build.sh b/publish/build.sh
new file mode 100644
index 0000000000000000000000000000000000000000..74fdbdf89f92f1646a9a37835a2ce7bd720b4666
--- /dev/null
+++ b/publish/build.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+cd publish 
+
+set -e
+
+node build_check.js
+
+set +e
+
+cd ../form 
+
+npm install
+
+npm run publish 
+
+cd ../publish 
+
+node build_step_0.js
+
+cd ../play
+
+/Applications/CocosCreator/Creator/2.4.0/CocosCreator.app/Contents/MacOS/CocosCreator --path "./" --build "platform=web-desktop;debug=true" --force
+
+echo "生成 web desktop 完成~!"
+
+cd ../publish 
+
+node build_step_1.js
+
+echo "build_step_1 完成~!"
+
+cd ../play
+
+/Applications/CocosCreator/Creator/2.4.4/CocosCreator.app/Contents/MacOS/CocosCreator --path "./" --build "platform=ios;debug=false;md5Cache=true;buildPath=build_ios;encryptJs=true;xxteaKey=6bbfce23-28b4-4a;zipCompressJs=true" --force
+
+echo "生成 ios 完成~!"
+
+cd ../publish 
+
+node build_step_2.js
+
+echo "build_step_2 完成~!"
+
+cd ../play
+
+/Applications/CocosCreator/Creator/2.4.4/CocosCreator.app/Contents/MacOS/CocosCreator --path "./" --build "platform=ios;debug=false;md5Cache=true;buildPath=build_android;appABIs=['armeabi-v7a','x86','x86_64','arm64-v8a'];encryptJs=true;xxteaKey=6bbfce23-28b4-4a;zipCompressJs=true" --force
+
+echo "生成 android 完成~!"
+
+cd ../publish 
+
+node build_step_3.js
+
+echo "build_step_3 完成~!"
+
+cd ../play
+
+/Applications/CocosCreator/Creator/2.4.4/CocosCreator.app/Contents/MacOS/CocosCreator --path "./" --build "platform=web-desktop;debug=false;buildPath=build_web_desktop" --force
+
+echo "生成 web-desktop 完成~!"
+
+cd ../publish 
+
+node build_step_4.js
+
+echo "build_step_4 完成~!"
\ No newline at end of file
diff --git a/publish/buildConfig.json b/publish/buildConfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..bd10daa5522973270ad187cd4d30a3eab954d4d2
--- /dev/null
+++ b/publish/buildConfig.json
@@ -0,0 +1,4 @@
+{
+	"platform": "web-desktop",
+	"debug": true
+}
\ No newline at end of file
diff --git a/publish/build_check.js b/publish/build_check.js
new file mode 100644
index 0000000000000000000000000000000000000000..9c1cd8f5511b0fb2fa100dffaf52647f0648189e
--- /dev/null
+++ b/publish/build_check.js
@@ -0,0 +1,32 @@
+let fs = require('fs');
+
+const dirNames = __dirname.split('/');
+const projectName = dirNames[dirNames.length - 2];
+const path = '../play/assets'
+let folderName = '';
+fs.readdirSync(path).find(fileName => {
+  const st = fs.statSync(`${path}/${fileName}`);
+  if (st.isDirectory()) {
+    folderName = fileName;
+  }
+});
+
+if (projectName != folderName) {
+  throw (`项目名(${projectName})与bundle文件夹名(${folderName})不相同`);
+}
+let same = false;
+const files = fs.readdirSync(`${path}/${folderName}/scene`);
+files.forEach(fileName => {
+  fileName.split('.').forEach((str, idx, arr) => {
+    if (str == 'fire') {
+      const sceneName = arr[idx - 1];
+      if (folderName == sceneName) {
+        same = true;
+      }
+    }
+  })
+});
+
+if (!same) {
+  throw (`bundle文件夹名称(${folderName})与scene名称不相同`);
+}
\ No newline at end of file
diff --git a/publish/build_step_0.js b/publish/build_step_0.js
new file mode 100644
index 0000000000000000000000000000000000000000..dff2b7f39c7e65309eda3f85cc99c9e54aa887f6
--- /dev/null
+++ b/publish/build_step_0.js
@@ -0,0 +1,16 @@
+let fs = require('fs');
+
+const path = '../play/assets'
+
+let folderName = '';
+fs.readdirSync(path).find(fileName => {
+  const st = fs.statSync(`${path}/${fileName}`);
+  if (st.isDirectory()) {
+    folderName = fileName;
+  }
+});
+const metaPath = `${path}/${folderName}.meta`;
+const metaDataStr = fs.readFileSync(metaPath);
+const metaData = JSON.parse(metaDataStr);
+metaData.isBundle = false;
+fs.writeFileSync(metaPath, JSON.stringify(metaData));
diff --git a/publish/build_step_1.js b/publish/build_step_1.js
new file mode 100644
index 0000000000000000000000000000000000000000..d0e5a85f1b302481296493ed4e69a62dafefb27c
--- /dev/null
+++ b/publish/build_step_1.js
@@ -0,0 +1,37 @@
+const { removeDir, copyDir, fix2 } = require('./utils');
+const compressing = require('compressing');
+let fs = require('fs');
+
+async function main() {
+  await removeDir('./publish/play');
+  await removeDir('./publish/form');
+
+  await copyDir('../play/build/web-desktop', './publish/play');
+  compressing.zip.uncompress('../form/publish/form.zip', './publish/form');
+
+  const data = await fs.readFileSync('./index.html');
+  await fs.writeFileSync('./publish/play/index.html', data);
+
+  await removeDir('../play/build/web-desktop');
+
+
+  const path = '../play/assets'
+  let folderName = '';
+  fs.readdirSync(path).find(fileName => {
+    const st = fs.statSync(`${path}/${fileName}`);
+    if (st.isDirectory()) {
+      folderName = fileName;
+    }
+  });
+  const metaPath = `${path}/${folderName}.meta`;
+  const metaDataStr = fs.readFileSync(metaPath);
+  const metaData = JSON.parse(metaDataStr);
+  metaData.isBundle = true;
+  metaData.isRemoteBundle = {
+    ios: true,
+    android: true
+  };
+  fs.writeFileSync(metaPath, JSON.stringify(metaData));
+}
+
+main();
\ No newline at end of file
diff --git a/publish/build_step_2.js b/publish/build_step_2.js
new file mode 100644
index 0000000000000000000000000000000000000000..e8d672bb9815dbd3abb0646451da6bc173a64795
--- /dev/null
+++ b/publish/build_step_2.js
@@ -0,0 +1,10 @@
+const { removeDir, copyDir, fix2 } = require('./utils');
+const compressing = require('compressing');
+
+async function main() {
+  await removeDir('./publish/ios');
+  await copyDir('../play/build_ios/jsb-link/remote', './publish/ios');
+  await removeDir('../play/build_ios/jsb-link');
+}
+
+main();
\ No newline at end of file
diff --git a/publish/build_step_3.js b/publish/build_step_3.js
new file mode 100644
index 0000000000000000000000000000000000000000..8fc7de02724b70b63223c50f212d90eb6f115e24
--- /dev/null
+++ b/publish/build_step_3.js
@@ -0,0 +1,11 @@
+const { removeDir, copyDir, fix2 } = require('./utils');
+const compressing = require('compressing');
+let fs = require('fs');
+
+async function main() {
+  await removeDir('./publish/android');
+  await copyDir('../play/build_android/jsb-link/remote', './publish/android');
+  await removeDir('../play/build_android/jsb-link');
+}
+
+main();
\ No newline at end of file
diff --git a/publish/build_step_4.js b/publish/build_step_4.js
new file mode 100644
index 0000000000000000000000000000000000000000..8992f0a54837b4d7c7ab6dd7f2c448e9e0eed529
--- /dev/null
+++ b/publish/build_step_4.js
@@ -0,0 +1,63 @@
+const { removeDir, copyDir, fix2 } = require('./utils');
+const compressing = require('compressing');
+let fs = require('fs');
+
+async function main() {
+  await removeDir('./publish/web_desktop');
+  const projectName = await getBundleName('../play/build_web_desktop/web-desktop/assets');
+  await copyDir(`../play/build_web_desktop/web-desktop/assets/${projectName}`, './publish/web_desktop');
+  await removeDir('../play/build_web_desktop');
+
+  const bundleData = {
+    ios: await getBundleData('./publish/ios'),
+    android: await getBundleData('./publish/android'),
+  }
+
+  fs.writeFileSync('./publish/config.json', JSON.stringify(bundleData));
+
+  const tarStream = new compressing.zip.Stream();
+  tarStream.addEntry('./publish/play');
+  tarStream.addEntry('./publish/form');
+  tarStream.addEntry('./publish/ios');
+  tarStream.addEntry('./publish/android');
+  tarStream.addEntry('./publish/web_desktop');
+  tarStream.addEntry('./publish/config.json');
+
+  const destStream = fs.createWriteStream(`publish/${getReleaseFileName()}.zip`);
+
+  tarStream.pipe(destStream);
+
+  console.log('打包完成!');
+}
+
+async function getBundleName(path) {
+  const paths = fs.readdirSync(path);
+  return paths.find(path => path != 'internal' && path !='main');
+}
+
+async function getBundleData(path) {
+  const bundleData = {
+    sceneName: '',
+    version: '',
+  }
+  const paths = fs.readdirSync(path);
+  bundleData.sceneName = paths[0];
+  const files = fs.readdirSync(path + '/' + bundleData.sceneName);
+  files.forEach(fileName => {
+    fileName.split('.').forEach((str, idx, arr) => {
+      if (str == 'config') {
+        bundleData.version = arr[idx + 1];
+      }
+    })
+  });
+  return bundleData;
+}
+
+function getReleaseFileName() {
+  let date = new Date();
+  let fileName = `Release_${date.getFullYear()}${fix2(date.getMonth() + 1)}${fix2(date.getDate())} `;
+  fileName += `${fix2(date.getHours())}-${fix2(date.getMinutes())}-${fix2(date.getSeconds())}`;
+  return fileName;
+}
+
+main();
\ No newline at end of file
diff --git a/publish/index.html b/publish/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..b0ca3a534085851fcf7119afc4cbeafaf635bed3
--- /dev/null
+++ b/publish/index.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+
+  <title>Cocos Creator | hello_world</title>
+
+  <meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1, minimum-scale=1,maximum-scale=1"/>
+  <meta name="apple-mobile-web-app-capable" content="yes"/>
+  <meta name="full-screen" content="yes"/>
+  <meta name="screen-orientation" content="portrait"/>
+  <meta name="x5-fullscreen" content="true"/>
+  <meta name="360-fullscreen" content="true"/>
+  
+  <meta name="renderer" content="webkit"/>
+  <meta name="force-rendering" content="webkit"/>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
+
+  <link rel="stylesheet" type="text/css" href="style-desktop.css"/>
+  <link rel="icon" href="favicon.ico"/>
+</head>
+<body>
+<!-- <h1 class="header">hello_world</h1> -->
+
+<!-- <div id="GameDiv" style="width:1280px; height: 720px;"> -->
+<canvas id="GameCanvas" width="100%" height="100%"></canvas>
+<div id="splash">
+  <div class="progress-bar stripes">
+    <span style="width: 0%"></span>
+  </div>
+</div>
+<!-- </div> -->
+
+<!-- <p class="footer">Made with <a href="https://www.cocos.com/products#CocosCreator" title="cocos creator">Cocos Creator</a></p> -->
+
+<script src="src/settings.js" charset="utf-8"></script>
+<script src="main.js" charset="utf-8"></script>
+<script type="text/javascript" src="//staging-teach.cdn.ireadabc.com/h5template/h5-static-lib/js/air.js"></script>
+
+
+<script type="text/javascript">
+(function () {
+    // open web debugger console
+    if (typeof VConsole !== 'undefined') {
+        window.vConsole = new VConsole();
+    }
+
+    var debug = window._CCSettings.debug;
+    var splash = document.getElementById('splash');
+    splash.style.display = 'block';
+
+    function loadScript (moduleName, cb) {
+      function scriptLoaded () {
+          document.body.removeChild(domScript);
+          domScript.removeEventListener('load', scriptLoaded, false);
+          cb && cb();
+      };
+      var domScript = document.createElement('script');
+      domScript.async = true;
+      domScript.src = moduleName;
+      domScript.addEventListener('load', scriptLoaded, false);
+      document.body.appendChild(domScript);
+    }
+
+    loadScript(debug ? 'cocos2d-js.js' : 'cocos2d-js-min.js', function () {
+      if (CC_PHYSICS_BUILTIN || CC_PHYSICS_CANNON) {
+        loadScript(debug ? 'physics.js' : 'physics-min.js', window.boot);
+      }
+      else {
+        window.boot();
+      }
+    });
+})();
+</script>
+
+</body>
+</html>
diff --git a/publish/package-lock.json b/publish/package-lock.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a1722797227f701681bde30e6b87ee9c3aa63d
--- /dev/null
+++ b/publish/package-lock.json
@@ -0,0 +1,253 @@
+{
+  "name": "publish",
+  "version": "1.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "bl": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz",
+      "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==",
+      "requires": {
+        "readable-stream": "^2.3.5",
+        "safe-buffer": "^5.1.1"
+      }
+    },
+    "buffer-alloc": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
+      "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
+      "requires": {
+        "buffer-alloc-unsafe": "^1.1.0",
+        "buffer-fill": "^1.0.0"
+      }
+    },
+    "buffer-alloc-unsafe": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
+      "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg=="
+    },
+    "buffer-crc32": {
+      "version": "0.2.13",
+      "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+      "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="
+    },
+    "buffer-fill": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
+      "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw="
+    },
+    "compressing": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/compressing/-/compressing-1.5.1.tgz",
+      "integrity": "sha512-1AGBR4Vh0/rpPKSXHoV9cerLo0CUlAhZ/xsJqU3a9+2cbSaFjWT3fk2MIGkCnbpk//DGWrcWw03rhKFQrA9RQw==",
+      "requires": {
+        "flushwritable": "^1.0.0",
+        "get-ready": "^1.0.0",
+        "iconv-lite": "^0.5.0",
+        "mkdirp": "^0.5.1",
+        "pump": "^3.0.0",
+        "streamifier": "^0.1.1",
+        "tar-stream": "^1.5.2",
+        "yauzl": "^2.7.0",
+        "yazl": "^2.4.2"
+      }
+    },
+    "core-util-is": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+    },
+    "end-of-stream": {
+      "version": "1.4.4",
+      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+      "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+      "requires": {
+        "once": "^1.4.0"
+      }
+    },
+    "fd-slicer": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+      "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
+      "requires": {
+        "pend": "~1.2.0"
+      }
+    },
+    "flushwritable": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/flushwritable/-/flushwritable-1.0.0.tgz",
+      "integrity": "sha1-PjKNj95BKtR+c44751C00pAENJg="
+    },
+    "fs-constants": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+      "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
+    },
+    "get-ready": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/get-ready/-/get-ready-1.0.0.tgz",
+      "integrity": "sha1-+RgX8emt7P6hOlYq38jeiDqzR4I="
+    },
+    "iconv-lite": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz",
+      "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==",
+      "requires": {
+        "safer-buffer": ">= 2.1.2 < 3"
+      }
+    },
+    "inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+    },
+    "isarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+    },
+    "minimist": {
+      "version": "1.2.5",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+    },
+    "mkdirp": {
+      "version": "0.5.5",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+      "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+      "requires": {
+        "minimist": "^1.2.5"
+      }
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "requires": {
+        "wrappy": "1"
+      }
+    },
+    "pend": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+      "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
+    },
+    "process-nextick-args": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+    },
+    "pump": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+      "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+      "requires": {
+        "end-of-stream": "^1.1.0",
+        "once": "^1.3.1"
+      }
+    },
+    "readable-stream": {
+      "version": "2.3.7",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+      "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+      "requires": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
+      },
+      "dependencies": {
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+        }
+      }
+    },
+    "safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+    },
+    "safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+    },
+    "streamifier": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/streamifier/-/streamifier-0.1.1.tgz",
+      "integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8="
+    },
+    "string_decoder": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "requires": {
+        "safe-buffer": "~5.1.0"
+      },
+      "dependencies": {
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+        }
+      }
+    },
+    "tar-stream": {
+      "version": "1.6.2",
+      "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz",
+      "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==",
+      "requires": {
+        "bl": "^1.0.0",
+        "buffer-alloc": "^1.2.0",
+        "end-of-stream": "^1.0.0",
+        "fs-constants": "^1.0.0",
+        "readable-stream": "^2.3.0",
+        "to-buffer": "^1.1.1",
+        "xtend": "^4.0.0"
+      }
+    },
+    "to-buffer": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
+      "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg=="
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+    },
+    "xtend": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+      "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
+    },
+    "yauzl": {
+      "version": "2.10.0",
+      "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
+      "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
+      "requires": {
+        "buffer-crc32": "~0.2.3",
+        "fd-slicer": "~1.1.0"
+      }
+    },
+    "yazl": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz",
+      "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==",
+      "requires": {
+        "buffer-crc32": "~0.2.3"
+      }
+    }
+  }
+}
diff --git a/publish/package.json b/publish/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..dd6a002f1c25440c2ce53f9dd139c3b60beab4a0
--- /dev/null
+++ b/publish/package.json
@@ -0,0 +1,14 @@
+{
+  "name": "publish",
+  "version": "1.0.0",
+  "description": "",
+  "main": "build.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "",
+  "license": "ISC",
+  "dependencies": {
+    "compressing": "^1.5.1"
+  }
+}
diff --git a/publish/publish/.keep b/publish/publish/.keep
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/publish/utils.js b/publish/utils.js
new file mode 100644
index 0000000000000000000000000000000000000000..24ee7470a121168b8a72434095d36888634d9a36
--- /dev/null
+++ b/publish/utils.js
@@ -0,0 +1,56 @@
+let fs = require('fs');
+
+module.exports = {
+  fix2: function (num) {
+    if (num >= 10) {
+      return '' + num;
+    } else {
+      return '0' + num;
+    }
+  },
+
+  copyDir: async function (src, dst) {
+    const exists = await fs.existsSync(dst);
+    if (!exists) {
+      await fs.mkdirSync(dst);
+    }
+    //读取目录
+    const paths = await fs.readdirSync(src);
+    for (let i = 0; i < paths.length; i++) {
+      let path = paths[i];
+      const newSrc = `${src}/${path}`;
+      const newDst = `${dst}/${path}`;
+      const st = await fs.statSync(newSrc);
+      if (st.isFile()) {
+        console.log('copy: ' + newDst);
+        const data = await fs.readFileSync(newSrc);
+        await fs.writeFileSync(newDst, data);
+      } else if (st.isDirectory()) {
+        arguments.callee(newSrc, newDst);
+      }
+    }
+  },
+
+  removeDir: async function (src) {
+    const exists = await fs.existsSync(src);
+    if (!exists) {
+      return;
+    }
+
+    //读取目录
+    const st = await fs.statSync(src);
+    const paths = await fs.readdirSync(src);
+    for (let i = 0; i < paths.length; i++) {
+      let path = paths[i];
+      const newSrc = `${src}/${path}`;
+      const st = await fs.statSync(newSrc);
+      if (st.isFile()) {
+        console.log('remove: ' + newSrc);
+        await fs.unlinkSync(newSrc);
+      } else if (st.isDirectory()) {
+        await arguments.callee(newSrc);
+      }
+    }
+    await fs.rmdirSync(src);
+  }
+}