Skip to content

Commit

Permalink
Chore: 重用chunk名字典等
Browse files Browse the repository at this point in the history
  • Loading branch information
Maorey committed Mar 9, 2020
1 parent a218dc4 commit d085709
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 55 deletions.
4 changes: 4 additions & 0 deletions .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ DEV_SERVER_PORT=9000
# DEV_SERVER_PAGE=/
# 是否使用https (不支持http2) 默认false
# DEV_SERVER_HTTPS=true
# 开发环境sourceMap https://webpack.js.org/configuration/devtool/#devtool
# 建议 eval(默认cheap-module-eval-source-map), 且配置 TypeScript 生成 sourceMap
# 这样更快, 且无同名.vue文件sourceMap冲突 (反正<template><style>也不能调试不是)
# DEV_TOOL=eval
# 代理接口服务地址,与 BASE_PATH 对应,比如 BASE_PATH1 对应 PROXY_TARGET1
PROXY_TARGET=https://127.0.0.1:9000/api

Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# 更新日志

## v 1.2.8

- 重用本地chunk名字典等

## v 1.2.7

- 优化路由、缓存及刷新策略
Expand Down
5 changes: 2 additions & 3 deletions build/development.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@
* https://github.com/neutrinojs/webpack-chain#getting-started
*/
module.exports = function(config) {
// eval 更快(默认cheap-module-eval-source-map), 且无同名.vue文件sourceMap冲突
// 反正<template><style>也不能调试不是)(TypeScript 有 sourceMap)
config.devtool('eval')
// https://webpack.js.org/configuration/devtool/#devtool
config.devtool(process.env.DEV_TOOL || 'eval')
/// 避免同名.vue文件sourceMap冲突 ///
// https://webpack.js.org/configuration/output/#outputdevtoolmodulefilenametemplate
// config.output.devtoolFallbackModuleFilenameTemplate(
Expand Down
6 changes: 3 additions & 3 deletions build/production.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @Author: 毛瑞
* @Date: 2019-04-01 13:28:06
*/
const rename = require('./rename')('chunkName')
const rename = require('./rename')('build/~fileName', 'chunkName')

const getLoaderOption = name => ({
limit: 4096,
Expand Down Expand Up @@ -119,7 +119,7 @@ module.exports = function(config, ENV, pages) {

/// 【优化(optimization)】 ///
// https://webpack.docschina.org/configuration/optimization 默认就好
config.optimization.runtimeChunk({ name: e => 'r_' + rename.get(e.name) })
config.optimization.runtimeChunk({ name: e => 'r_' + rename.short(e.name) })

/// 【代码分割(optimization.splitChunks 不能config.merge({}))】 ///
// https://webpack.docschina.org/plugins/split-chunks-plugin
Expand Down Expand Up @@ -174,7 +174,7 @@ module.exports = function(config, ENV, pages) {
}
CONFS[entry] = 1
entry = entry.replace(REG, STR)
name = prefix + rename.get(name)
name = prefix + rename.short(name)
group[name] = {
name,
chunks: 'all',
Expand Down
18 changes: 9 additions & 9 deletions build/rename.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
const updateJSON = require('./updateJSON')
const shortString = require('./shortString')

/** 重命名 vender chunks (命名映射:build/~fileName)
* vendors.main.other.user.d0ae3f07.77d.js => v.wzS.d0ae3f07.77d.js
* @param {String} des 缩写描述
* @param {Object} DIC 缩写字典 eg: { index: 'i' }
/** 字典重命名: vendors.main.other.user.d0ae3f07.77d.js => v.wzS.d0ae3f07.77d.js
* @param {String} file 字典文件
* @param {Object} key 字典键值
*
* @returns {Function} 缩写函数
* @returns {Function} 模块重命名函数:rename, rename.short: 字符串缩写函数
*/
module.exports = function(des = '', DIC = {}) {
const short = shortString(DIC)// 字符串缩写函数
process.on('beforeExit', () => updateJSON('build/~fileName', des, DIC))
module.exports = function(file, key) {
const DIC = updateJSON(file, key) || {} // 重用已有字典
const short = shortString(DIC) // 字符串缩写函数
process.on('beforeExit', () => updateJSON(file, key, DIC))

/** 重命名 vender chunks (命名映射:build/~fileName)
* vendors.main.other.user.d0ae3f07.77d.js => v.wzS.d0ae3f07.77d.js
Expand All @@ -37,6 +37,6 @@ module.exports = function(des = '', DIC = {}) {
return name
}

rename.get = short
rename.short = short // 暴露缩写函数
return rename
}
11 changes: 10 additions & 1 deletion build/updateJSON.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* @Description: 修改JSON文件
* @Description: 读取/更新JSON文件
* @Author: 毛瑞
* @Date: 2019-07-03 13:24:19
*/
Expand All @@ -8,6 +8,11 @@ const path = require('path')

const REG_SPLIT = /\.(?!['"])/

/** 读取/更新json文件
* @param {string} fileName 文件名(含路径)
* @param {string} key 目标对象属性, 支持多级, 比如: 'a.b.c'
* @param {any} value 要更新的值, 不传则返回目标值
*/
module.exports = function(fileName, key, value) {
fileName = path.resolve(fileName)
key = key.split(REG_SPLIT)
Expand All @@ -33,6 +38,10 @@ module.exports = function(fileName, key, value) {
current = parent[k] === undefined ? (parent[k] = {}) : parent[k]
}

if (arguments.length < 3) {
return current
}

if (
typeof value === 'object' && typeof current === 'object'
? JSON.stringify(current) !== JSON.stringify(value)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "vue-tpl",
"author": "毛瑞 <[email protected]>",
"version": "1.2.7",
"version": "1.2.8",
"private": false,
"license": "MIT",
"keywords": [
Expand Down
81 changes: 43 additions & 38 deletions src/components/ChooserAsyncFunctional.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,28 @@ export const enum status {
empty = 4,
success = 5,
}
const enum PROPS {
get = 'get',
error = 'error',
tag = 'tag',
filter = 'filter',
components = 'components',
}
type component = status | string | Component
type filter = (data: any) => { data: any; comp: component } | void
type state = {
/// props ///
/** 未匹配到任何组件但有数据时使用的组件[默认‘div’] 若字典存在, tag为字符串, 则优先从字典取
*/
[PROPS.tag]?: component
tag?: component
/** 查询函数
*/
[PROPS.get]?: () => Promise<any>
get?: () => Promise<any>
/** 选择组件函数 若字典存在, 返回的comp属性为字符串, 则优先从字典取
*/
[PROPS.filter]?: filter
filter?: filter
/** 自定义处理查询错误时的展示(接受参数为错误对象)
*/
[PROPS.error]?: status | ((err: Error) => component)
error?: status | ((err: Error) => component)
/** 组件字典 当filter返回string时即从字典取对应组件
*/
[PROPS.components]?: IObject<Component>
components?: IObject<Component>
/** 类似 v-once, 默认 false
*/
once?: boolean

/// 私有状态 ///
/** 当前组件 (响应式属性) */
Expand All @@ -64,10 +60,10 @@ type state = {
o?: any
/** 绑定数据 */
d?: any
/** 上一次状态 */
c?: component
/** 当前组件缓存 */
n?: VNode
/** 上一次组件(once时比较) */
c?: component
}

function watch(state: state) {
Expand Down Expand Up @@ -108,13 +104,14 @@ function get(state: state) {
})
}

// get 和 error改变走 get函数 否则watch
// get和error改变走get否则watch
const DIC_PROPS = {
[PROPS.get]: 1,
[PROPS.error]: 1,
[PROPS.tag]: 1,
[PROPS.filter]: 1,
[PROPS.components]: 1,
get: 1,
error: 1,
tag: 1,
filter: 1,
components: 1,
once: 1,
}
const DIC_EVENTS: IObject<status> = {
none: status.none,
Expand All @@ -136,19 +133,20 @@ function init(state: state, context: RenderContext) {
let target
/// props/attrs ///
for (prop in DIC_PROPS) {
if ((target = props[prop] || attrs[prop]) !== state[prop as PROPS]) {
if ((target = props[prop] || attrs[prop]) !== (state as any)[prop]) {
isSame = false
fun || ((prop === PROPS.get || prop === PROPS.error) && (fun = get))
fun || ((prop === 'get' || prop === 'error') && (fun = get))
}
state[prop as PROPS] = target
;(state as any)[prop] = target
attrs[prop] && (attrs[prop] = null) // 防止(特别是function)toString到dom属性
}

/// on ///
for (prop in DIC_EVENTS) {
state.f[DIC_EVENTS[prop]] = on[prop]
}

return isSame || (fun || watch)(state)
return isSame ? state.once : (fun || watch)(state)
}

function getState(CACHE: any, key: any) {
Expand Down Expand Up @@ -191,7 +189,7 @@ function call(hooks: state['f'][status], context: RenderContext) {
*
* props: 见: type state 注释 【注意】: get/error 变化时会重新请求
* events: 见: const enum status 键值
* slots: 支持默认插槽/默认作用域插槽 二选一 (二者都有时无法确定顺序, 所以只能二选一)
* slots: 支持默认插槽/默认作用域插槽二选一(二者都有时无法确定顺序, )
* 示例:
* <template>
* <ChooserAsyncFunctional :key="key" :get="get" @error="handleError">
Expand All @@ -203,33 +201,40 @@ function call(hooks: state['f'][status], context: RenderContext) {
* ( import 咋没得文档呢, 因为tsx么... ┐(: ´ ゞ`)┌ )
*/
export default (context: RenderContext) => {
let parent // 工具人
parent = context.parent
let temp // 工具人
temp = context.parent
const data = context.data
const state = getState(parent, data.key || '')
if (parent.$el && !parent.$el.parentNode) {
return state.n
const state = getState(temp, data.key || '')
if (temp.$el && !temp.$el.parentNode) {
return state.n // 父组件未挂载
}

parent = init(state, context)
temp = init(state, context)
const Comp: any = state.i.i // 收集依赖
if (parent && Comp === state.c) {
return state.n
if (temp && Comp === state.c) {
return state.n // once & 自身未变化
}

state.c = Comp
call(state.f[Comp as status] || state.f[status.success], context)

switch (Comp) {
case status.none:
return (state.n = <i key='n' style="display:none" />)
return (state.n = <i key={data.key + 'w'} style="display:none" />)
case status.loading:
return (state.n = <Loading key="l" />)
return (state.n = <Loading key={data.key + 'x'} />)
case status.empty:
return (state.n = (
<Info key="e" icon="el-icon-info" type="info" msg="empty" retry="" />
<Info
key={data.key + 'y'}
icon="el-icon-info"
type="info"
msg="empty"
retry=""
/>
))
case status.error:
return (state.n = <Info key="i" on={state.$} />)
return (state.n = <Info key={data.key + 'z'} on={state.$} />)
default:
data.props = context.props
data.props.data = state.d.data // 添加 props: data
Expand All @@ -238,7 +243,7 @@ export default (context: RenderContext) => {
return (state.n = (
<Comp {...data}>
{context.slots().default ||
((parent = context.scopedSlots.default) && parent(state.d))}
((temp = context.scopedSlots.default) && temp(state.d))}
</Comp>
))
}
Expand Down
6 changes: 6 additions & 0 deletions src/components/Info.vue
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ export default class extends Vue {
border: $borderBase;
border-radius: $borderRadiusCircle;
}
// 消息
p,
a {
margin: 5px 0;
font-size: $small;
}
// 重试
a {
display: block;
Expand Down

0 comments on commit d085709

Please sign in to comment.