Skip to content
This repository has been archived by the owner on Jun 24, 2021. It is now read-only.

Commit

Permalink
support spa and compress
Browse files Browse the repository at this point in the history
  • Loading branch information
JuneAndGreen committed Nov 14, 2018
1 parent 1f44a05 commit ab3e425
Show file tree
Hide file tree
Showing 22 changed files with 415 additions and 79 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ module.exports = {
| output | String || 输出目录,输出的内容是一个完整可运行的小程序项目,默认为当前运行目录下的 h5\_to\_miniprogram\_output 目录中 |
| config | String || 配置文件路径 |
| extend | String/Array || 扩展实现文件路径,支持以数组方式传入多个扩展,下面会作详细介绍使用方式 |
| compress | Boolean/Object || 压缩配置,当传入 true 时,表示所有压缩子项都为 true |
| compress.jsInH5 | Boolean || 是否压缩原 h5 页面中的 js 和生成的初始抽象语法树代码 |
| compress.cssInH5 | Boolean || 是否压缩原 h5 页面中的 css 和默认载入的初始 wxss |

以下是一个使用此工具的范例:

Expand All @@ -70,6 +73,10 @@ toMiniprogram({
output: '/output',
config: '/config.js',
extend: '/extend.js',
compress: {
jsInH5: true,
cssInH5: true,
},
}).then(res => {
console.log('done')
}).catch(err => {
Expand Down Expand Up @@ -109,6 +116,7 @@ module.exports = function(loadModule, moduleName) {
1. bom 相关

* Cookie
* History
* LocalStorage
* Location
* Navigator
Expand All @@ -131,7 +139,7 @@ module.exports = function(loadModule, moduleName) {

* Attribute
* ClassList
* ~~Comment~~
* Comment
* Element
* Node
* styleList
Expand Down
4 changes: 4 additions & 0 deletions UPDATE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## next version

* 支持 cookie
* 支持 hashchange 事件
* 支持 document.createComment 接口
* 支持 history
* 支持压缩原 h5 页面代码
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
"author": "wechat-miniprogram",
"license": "MIT",
"devDependencies": {
"babel-plugin-minify-mangle-names": "^0.5.0",
"cssnano": "^4.1.7",
"eslint": "^5.3.0",
"eslint-config-airbnb-base": "13.1.0",
"eslint-plugin-import": "^2.14.0",
Expand Down
24 changes: 20 additions & 4 deletions src/css/adjust.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/

const postcss = require('postcss')
const cssnano = require('cssnano')

const load = require('../template/adapter')
const config = require('../config')
Expand Down Expand Up @@ -124,13 +125,28 @@ const adjustRemPlugin = function (rem) {
})
}

module.exports = function (code, config = {}) {
module.exports = async function (code, config = {}) {
const resFilter = typeof config.resFilter === 'function' ? config.resFilter : (src => src)
const rem = typeof config.rem === 'number' && isFinite(config.rem) ? config.rem : 0
const entryKey = config.entryKey

return postcss([replaceTagNamePlugin, formatPlugin, replaceImagePlugin(resFilter, entryKey), adjustRemPlugin(rem)]).process(code, {
const needCompress = config.needCompress
const pluginList = [replaceTagNamePlugin, formatPlugin, replaceImagePlugin(resFilter, entryKey), adjustRemPlugin(rem)]

if (needCompress) {
// 压缩
pluginList.push(cssnano({
preset: ['default', {
discardComments: {
removeAll: true,
},
}]
}))
}

code = await postcss(pluginList).process(code, {
from: undefined, // 主要是不想看到那个 warning
map: null,
}).css
})

return code.css
}
9 changes: 6 additions & 3 deletions src/css/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ module.exports = {
const cssList = options.cssList
const config = options.config
const entryKey = options.entryKey
const needCompress = !!options.compress.cssInH5
const dirPath = path.dirname(entry)
const adjustConfig = {entryKey, ...config}
const adjustConfig = {entryKey, needCompress, ...config}

let content = [
'/* original user agent stylesheet */\n@import "../../common/wxss/original.wxss";'
Expand All @@ -42,8 +43,9 @@ module.exports = {
// 写入 common 目录
const extname = path.extname(cssPath)
const filename = `${path.basename(cssPath, extname)}-${_.hash(linkContent)}.wxss`
const adjustContent = await adjust(linkContent, adjustConfig)

await _.writeFile(path.join(commonOutput, filename), adjust(linkContent, adjustConfig))
await _.writeFile(path.join(commonOutput, filename), adjustContent)
content.push(`/* link style: ${css.src} */\n@import "../../common/wxss/${filename}";`)
}
}
Expand All @@ -52,6 +54,7 @@ module.exports = {
content = content.join('\n\n')

// 输出到 output 中
await _.writeFile(output, adjust(content, adjustConfig))
const adjustContent = await adjust(content, adjustConfig)
await _.writeFile(output, adjustContent)
}
}
7 changes: 7 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ module.exports = async function (options) {
const extendPath = options.extend
let entry = options.entry || {}
const output = options.output || path.join(process.pwd(), './h5_to_miniprogram_output')
const compress = options.compress === true ? {
jsInH5: true,
cssInH5: true,
} : (options.compress || {})

let config = {}
let indexEntry = '' // 首页
Expand Down Expand Up @@ -72,6 +76,7 @@ module.exports = async function (options) {
cssList: entryInfo.style,
config,
entryKey,
compress,
})

// 生成脚本
Expand All @@ -82,6 +87,7 @@ module.exports = async function (options) {
jsList: entryInfo.script,
body: entryInfo.body,
entryKey,
compress,
})

// 生成配置
Expand All @@ -96,5 +102,6 @@ module.exports = async function (options) {
entryKeys,
configPath,
extendPath,
compress,
})
}
18 changes: 12 additions & 6 deletions src/js/adjust.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ function adjustTopFuncDecl(ast, magicString) {
return magicString.toString()
}

module.exports = function (code) {
module.exports = async function (code, needCompress) {
const comments = []
const ast = acorn.parse(code, {
sourceType: 'script',
Expand All @@ -74,12 +74,18 @@ module.exports = function (code) {
code = replaceGlobal(ast, magicString)
code = adjustTopFuncDecl(ast, magicString)

const plugins = []
if (needCompress) {
plugins.push('babel-plugin-minify-mangle-names')
}

// 转换代码
code = babel.transformSync(code, {
minified: false,
compact: false,
code = await babel.transform(code, {
minified: needCompress,
compact: needCompress, // 不包含多余的空格符和换行符
comments: false,
}).code
plugins,
})

return code
return code.code
}
19 changes: 12 additions & 7 deletions src/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ module.exports = {
const jsList = options.jsList
const body = options.body
const entryKey = options.entryKey
const needCompress = !!options.compress.jsInH5
const dirPath = path.dirname(entry)

// 依赖
Expand All @@ -36,7 +37,9 @@ module.exports = {
// 遍历页面中的静态 js
for (const js of jsList) {
if (js.type === 'inner') {
content.push(`${config.indent}/* inner script */\n${adjust(js.content)}`)
const adjustContent = await adjust(js.content, needCompress)

content.push(`${config.indent}/* inner script */\n${adjustContent}`)
} else if (js.type === 'outer') {
let jsPath = js.src
let srcContent
Expand All @@ -54,14 +57,15 @@ module.exports = {
// 写入 common 目录
const extname = path.extname(jsPath)
const filename = `${path.basename(jsPath, extname)}-${_.hash(srcContent)}.js`
const adjustContent = await adjust(srcContent, needCompress)

await _.writeFile(path.join(commonOutput, filename), [
'module.exports = function(window, document) {',
'let module = undefined;',
'let global = window;',
`(function() {${adjust(srcContent)}}).call(window)`, // 保证 this 指向 window
'module.exports=function(window,document){',
'var module=undefined;',
'var global=window;',
`(function(){${adjustContent}}).call(window)`, // 保证 this 指向 window
'};',
].join('\n'))
].join(''))
content.push(`${config.indent}/* outer script: ${js.src} */\n${config.indent}require('../../common/js/${filename}')(window, document);`)
}
}
Expand All @@ -79,6 +83,7 @@ module.exports = {
await _.writeFile(output, content)

// 输出页面 ast
await _.writeFile(path.join(path.dirname(output), './ast.js'), `module.exports = ${JSON.stringify(body)};`)
const astContent = needCompress ? JSON.stringify(body) : JSON.stringify(body, null, config.indent)
await _.writeFile(path.join(path.dirname(output), './ast.js'), `module.exports = ${astContent};`)
}
}
90 changes: 80 additions & 10 deletions src/template/adapter/bom/history.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,49 @@
/**
* 暂不维护跳转后页面的历史,不做页面刷新的操作
*/
const load = require('../index')

const Location = load('Location')
const EventTarget = load('EventTarget')

class History {
constructor() {
this._stack = []
class History extends EventTarget {
constructor(location) {
super()

this._location = location
this._stack = [{
state: null,
title: '',
url: location.href,
}]
this._currentIndex = 0

this._location.addEventListener('_addToHistory', evt => {
this._currentIndex++
this._stack = this._stack.slice(0, this._currentIndex)
this._stack.push({
state: null,
title: '',
url: evt.href
})
})
}

/**
* 检查是否同源
*/
_checkOrigin(url) {
const {protocol, hostname, port} = Location._$parse(url)

return (!protocol || this._location.protocol === protocol) && (!hostname || this._location.hostname === hostname) && ((!hostname && !port) || this._location.port === port)
}

/**
* 对外属性和方法
*/
get state() {

const current = this._stack[this._currentIndex]
return current && current.state || null
}

get length() {
Expand All @@ -28,23 +60,61 @@ class History {

go(delta) {
if (typeof delta === 'number') {
const next = this._currentIndex + delta

if (next >= 0 && next < this._stack.length && this._currentIndex !== next) {
this._currentIndex = next
// 替换 href,但不做跳转(理论上此处应该做跳转,但是在小程序环境里不适合)
this._location._$setHrefWithoutCheck(this._stack[this._currentIndex].url)

this._$trigger('popstate', {
event: {
state: this.state
}
})
}
} else {
// 刷新当前页面
// TODO
this._location.reload()
}
}

pushState(state, title, url) {
pushState(state = null, title, url) {
if (!url || typeof url !== 'string') return

const {
protocol, hostname, port, pathname, hash, search
} = Location._$parse(url)
if (this._checkOrigin(url)) {
// 同源才允许操作
if (title && typeof title === 'string') {
// 设置标题
wx.setNavigationBarTitle({title})
}


this._currentIndex++
this._stack = this._stack.slice(0, this._currentIndex)

// 替换 href,但不做跳转
this._location._$setHrefWithoutCheck(url)

this._stack.push({state, title, url: this._location.href})
}
}

replaceState(state, title, url) {
replaceState(state = null, title, url) {
if (!url || typeof url !== 'string') return

if (this._checkOrigin(url)) {
// 同源才允许操作
if (title && typeof title === 'string') {
// 设置标题
wx.setNavigationBarTitle({title})
}

// 替换 href,但不做跳转
this._location._$setHrefWithoutCheck(url)

this._stack.splice(this._currentIndex, 1, {state, title, url: this._location.href})
}
}
}

Expand Down
Loading

0 comments on commit ab3e425

Please sign in to comment.