Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
m0_68066342
uni-app
提交
65049f2f
U
uni-app
项目概览
m0_68066342
/
uni-app
与 Fork 源项目一致
Fork自
DCloud / uni-app
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
uni-app
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
65049f2f
编写于
2月 19, 2022
作者:
S
songyu
提交者:
折腾笔记
4月 11, 2022
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 为微信小程序环境增加构建独立分包能力
上级
dc6f7d4d
变更
33
隐藏空白更改
内联
并排
Showing
33 changed file
with
1939 addition
and
28 deletion
+1939
-28
packages/uni-cli-shared/lib/cache.js
packages/uni-cli-shared/lib/cache.js
+10
-3
packages/uni-cli-shared/lib/pages.js
packages/uni-cli-shared/lib/pages.js
+15
-1
packages/uni-mp-weixin/lib/analyze-wxcomponent-dependency/collect-dependency.js
.../lib/analyze-wxcomponent-dependency/collect-dependency.js
+166
-0
packages/uni-mp-weixin/lib/analyze-wxcomponent-dependency/constant.js
...-mp-weixin/lib/analyze-wxcomponent-dependency/constant.js
+11
-0
packages/uni-mp-weixin/lib/analyze-wxcomponent-dependency/index.js
...uni-mp-weixin/lib/analyze-wxcomponent-dependency/index.js
+80
-0
packages/uni-mp-weixin/lib/analyze-wxcomponent-dependency/utils.js
...uni-mp-weixin/lib/analyze-wxcomponent-dependency/utils.js
+44
-0
packages/uni-mp-weixin/lib/createIndependentPlugin.js
packages/uni-mp-weixin/lib/createIndependentPlugin.js
+37
-0
packages/uni-mp-weixin/lib/independent-plugins/add-share-ability-to-runtime-plugin.js
...ndependent-plugins/add-share-ability-to-runtime-plugin.js
+61
-0
packages/uni-mp-weixin/lib/independent-plugins/add-weixin-mp-runtime-plugin.js
...n/lib/independent-plugins/add-weixin-mp-runtime-plugin.js
+77
-0
packages/uni-mp-weixin/lib/independent-plugins/app-interceptor-plugin.js
...-weixin/lib/independent-plugins/app-interceptor-plugin.js
+64
-0
packages/uni-mp-weixin/lib/independent-plugins/generate-indepndent-entry-plugin.js
...b/independent-plugins/generate-indepndent-entry-plugin.js
+46
-0
packages/uni-mp-weixin/lib/independent-plugins/inject-entry-to-independent-plugin.js
...independent-plugins/inject-entry-to-independent-plugin.js
+36
-0
packages/uni-mp-weixin/lib/independent-plugins/inject-main-css-to-independent-plugin.js
...ependent-plugins/inject-main-css-to-independent-plugin.js
+133
-0
packages/uni-mp-weixin/lib/independent-plugins/insert-weui-css-to-independent-plugin.js
...ependent-plugins/insert-weui-css-to-independent-plugin.js
+20
-0
packages/uni-mp-weixin/lib/independent-plugins/modify-uniapp-webpack-config-Plugin.js
...ndependent-plugins/modify-uniapp-webpack-config-Plugin.js
+10
-0
packages/uni-mp-weixin/lib/independent-plugins/optimize-components-position/analyze.js
...dependent-plugins/optimize-components-position/analyze.js
+112
-0
packages/uni-mp-weixin/lib/independent-plugins/optimize-components-position/constant.js
...ependent-plugins/optimize-components-position/constant.js
+12
-0
packages/uni-mp-weixin/lib/independent-plugins/optimize-components-position/copy-outer-components-for-independent.js
...ponents-position/copy-outer-components-for-independent.js
+228
-0
packages/uni-mp-weixin/lib/independent-plugins/optimize-components-position/copy-wx-components-on-demand/analyze-go-direction.js
...tion/copy-wx-components-on-demand/analyze-go-direction.js
+55
-0
packages/uni-mp-weixin/lib/independent-plugins/optimize-components-position/copy-wx-components-on-demand/collect-wx-component-used-status.js
...-components-on-demand/collect-wx-component-used-status.js
+44
-0
packages/uni-mp-weixin/lib/independent-plugins/optimize-components-position/copy-wx-components-on-demand/index.js
...components-position/copy-wx-components-on-demand/index.js
+55
-0
packages/uni-mp-weixin/lib/independent-plugins/optimize-components-position/index.js
...independent-plugins/optimize-components-position/index.js
+36
-0
packages/uni-mp-weixin/lib/independent-plugins/optimize-components-position/util.js
.../independent-plugins/optimize-components-position/util.js
+157
-0
packages/uni-mp-weixin/lib/independent-plugins/run-default-app-plugin.js
...-weixin/lib/independent-plugins/run-default-app-plugin.js
+32
-0
packages/uni-mp-weixin/lib/independent-plugins/split-independent-chunks-plugin.js
...ib/independent-plugins/split-independent-chunks-plugin.js
+261
-0
packages/uni-mp-weixin/lib/independent-plugins/utils.js
packages/uni-mp-weixin/lib/independent-plugins/utils.js
+16
-0
packages/uni-mp-weixin/lib/runtime/index.js
packages/uni-mp-weixin/lib/runtime/index.js
+4
-0
packages/uni-mp-weixin/lib/runtime/wxMpRuntime.js
packages/uni-mp-weixin/lib/runtime/wxMpRuntime.js
+35
-0
packages/uni-mp-weixin/lib/uni.config.js
packages/uni-mp-weixin/lib/uni.config.js
+13
-7
packages/vue-cli-plugin-uni/lib/mp/index.js
packages/vue-cli-plugin-uni/lib/mp/index.js
+4
-1
packages/vue-cli-plugin-uni/lib/split-chunks.js
packages/vue-cli-plugin-uni/lib/split-chunks.js
+14
-2
packages/webpack-uni-mp-loader/lib/plugin/generate-component.js
...es/webpack-uni-mp-loader/lib/plugin/generate-component.js
+18
-3
packages/webpack-uni-mp-loader/lib/plugin/generate-json.js
packages/webpack-uni-mp-loader/lib/plugin/generate-json.js
+33
-11
未找到文件。
packages/uni-cli-shared/lib/cache.js
浏览文件 @
65049f2f
...
@@ -104,9 +104,14 @@ function updateComponentJson (name, jsonObj, usingComponents = true, type = 'Com
...
@@ -104,9 +104,14 @@ function updateComponentJson (name, jsonObj, usingComponents = true, type = 'Com
}
}
function
updateUsingGlobalComponents
(
name
,
usingGlobalComponents
)
{
function
updateUsingGlobalComponents
(
name
,
usingGlobalComponents
)
{
if
(
supportGlobalUsingComponents
)
{
const
manifestConfig
=
process
.
UNI_MANIFEST
;
return
const
weixinConfig
=
manifestConfig
[
'
mp-weixin
'
];
const
independentSwitch
=
!!
weixinConfig
.
independentSwitch
;
if
(
!
independentSwitch
&&
supportGlobalUsingComponents
)
{
return
;
}
}
const
oldJsonStr
=
getJsonFile
(
name
)
const
oldJsonStr
=
getJsonFile
(
name
)
if
(
oldJsonStr
)
{
// update
if
(
oldJsonStr
)
{
// update
const
jsonObj
=
JSON
.
parse
(
oldJsonStr
)
const
jsonObj
=
JSON
.
parse
(
oldJsonStr
)
...
@@ -342,6 +347,7 @@ module.exports = {
...
@@ -342,6 +347,7 @@ module.exports = {
getWXComponents
,
getWXComponents
,
getGlobalUsingComponents
,
getGlobalUsingComponents
,
updateAppJson
,
updateAppJson
,
updateJsonFile
,
updatePageJson
,
updatePageJson
,
updateProjectJson
,
updateProjectJson
,
updateComponentJson
,
updateComponentJson
,
...
@@ -353,5 +359,6 @@ module.exports = {
...
@@ -353,5 +359,6 @@ module.exports = {
updateComponentGenerics
,
updateComponentGenerics
,
updateGenericComponents
,
updateGenericComponents
,
getChangedJsonFileMap
,
getChangedJsonFileMap
,
getSpecialMethods
getSpecialMethods
,
supportGlobalUsingComponents
}
}
packages/uni-cli-shared/lib/pages.js
浏览文件 @
65049f2f
...
@@ -205,10 +205,24 @@ function parsePages (pagesJson, pageCallback, subPageCallback) {
...
@@ -205,10 +205,24 @@ function parsePages (pagesJson, pageCallback, subPageCallback) {
}
}
function
parseEntry
(
pagesJson
)
{
function
parseEntry
(
pagesJson
)
{
const
mainJsPath
=
path
.
resolve
(
process
.
env
.
UNI_INPUT_DIR
,
getMainEntry
())
process
.
UNI_ENTRY
=
{
process
.
UNI_ENTRY
=
{
'
common/main
'
:
path
.
resolve
(
process
.
env
.
UNI_INPUT_DIR
,
getMainEntry
())
'
common/main
'
:
mainJsPath
}
const
manifestConfig
=
process
.
UNI_MANIFEST
;
const
weixinConfig
=
manifestConfig
[
'
mp-weixin
'
]
||
{};
const
independentSwitch
=
!!
weixinConfig
.
independentSwitch
;
if
(
independentSwitch
)
{
Object
.
values
(
process
.
UNI_SUBPACKAGES
).
forEach
(({
root
,
independent
=
false
})
=>
{
if
(
root
&&
independent
)
{
const
pkgRootMainJsKey
=
`
${
root
}
/common/main`
;
// const pkgRootMainJsPath = `${process.env.UNI_INPUT_DIR}/${root}/main.js`;
process
.
UNI_ENTRY
[
pkgRootMainJsKey
]
=
mainJsPath
;
}
});
}
}
process
.
UNI_SUB_PACKAGES_ROOT
=
{}
process
.
UNI_SUB_PACKAGES_ROOT
=
{}
process
.
UNI_NVUE_ENTRY
=
{}
process
.
UNI_NVUE_ENTRY
=
{}
...
...
packages/uni-mp-weixin/lib/analyze-wxcomponent-dependency/collect-dependency.js
0 → 100644
浏览文件 @
65049f2f
const
path
=
require
(
'
path
'
);
const
fs
=
require
(
'
fs-extra
'
);
const
htmlparser2
=
require
(
'
htmlparser2
'
);
const
{
MpComponentFileExtension
}
=
require
(
'
./constant
'
);
const
{
transformScript
,
resolveToContext
}
=
require
(
'
./utils.js
'
);
const
{
parse
}
=
require
(
'
@babel/parser
'
);
const
{
default
:
traverse
}
=
require
(
'
@babel/traverse
'
);
class
CollectDependency
{
constructor
(
context
,
readFileSync
,
existsSync
,
addExtension
)
{
this
.
context
=
context
;
this
.
existsSync
=
existsSync
||
fs
.
existsSync
.
bind
(
fs
);
this
.
readFileSync
=
readFileSync
||
fs
.
readFileSync
.
bind
(
fs
);
this
.
addExtension
=
addExtension
;
}
getWxCssDeps
(
file
)
{
const
deps
=
[];
const
dirName
=
path
.
dirname
(
file
);
let
content
=
this
.
readFileSync
(
file
,
'
utf-8
'
);
if
(
content
instanceof
Buffer
)
{
content
=
content
.
toString
(
'
utf-8
'
);
}
const
importRegExp
=
/@import
\s
*
[
'"
](
.+
)[
'"
]
;*/g
;
let
matched
;
while
((
matched
=
importRegExp
.
exec
(
content
))
!==
null
)
{
if
(
!
matched
[
1
])
{
continue
;
}
const
wxssFile
=
resolveToContext
(
dirName
,
matched
[
1
],
this
.
context
);
if
(
this
.
existsSync
(
wxssFile
))
{
deps
.
push
(
wxssFile
);
}
}
return
deps
;
};
getWxHtmlDeps
(
file
)
{
const
deps
=
[];
const
dirName
=
path
.
dirname
(
file
);
let
content
=
this
.
readFileSync
(
file
,
'
utf-8
'
);
if
(
content
instanceof
Buffer
)
{
content
=
content
.
toString
(
'
utf-8
'
);
}
// https://developers.weixin.qq.com/miniprogram/dev/reference/wxml/import.html
// WXML 提供两种文件引用方式import和include。
const
targetTags
=
[
'
import
'
,
'
include
'
,
'
wxs
'
];
const
existsSync
=
this
.
existsSync
;
const
htmlParser
=
new
htmlparser2
.
Parser
({
onopentag
(
name
,
attribs
=
{})
{
if
(
!
targetTags
.
includes
(
name
))
{
return
;
}
const
{
src
}
=
attribs
;
if
(
!
src
)
{
return
;
}
const
wxmlFile
=
resolveToContext
(
dirName
,
src
,
this
.
context
);
console
.
log
(
wxmlFile
);
if
(
existsSync
(
wxmlFile
))
{
deps
.
push
(
wxmlFile
);
}
},
});
htmlParser
.
write
(
content
);
htmlParser
.
end
();
return
deps
;
}
getJsonDeps
(
file
)
{
const
deps
=
[];
const
dirName
=
path
.
dirname
(
file
);
const
fileContent
=
this
.
readFileSync
(
file
);
const
{
usingComponents
}
=
JSON
.
parse
(
fileContent
);
if
(
usingComponents
&&
typeof
usingComponents
===
'
object
'
)
{
Object
.
values
(
usingComponents
).
forEach
((
component
)
=>
{
component
=
resolveToContext
(
dirName
,
component
,
this
.
context
);
// 每个组件都需要判断 js/json/wxml/wxss 文件是否存在
MpComponentFileExtension
.
forEach
((
ext
)
=>
{
const
file
=
this
.
addExtension
(
component
,
ext
);
if
(
this
.
existsSync
(
file
))
{
deps
.
push
(
file
);
}
});
});
}
return
deps
;
}
getJsDeps
(
file
)
{
const
deps
=
[];
const
dirName
=
path
.
dirname
(
file
);
// 读取 js 文件内容
let
content
=
this
.
readFileSync
(
file
,
'
utf-8
'
);
if
(
content
instanceof
Buffer
)
{
content
=
content
.
toString
(
'
utf-8
'
);
}
// 将代码转化为 AST
const
ast
=
parse
(
content
,
{
sourceType
:
'
module
'
,
plugins
:
[
'
exportDefaultFrom
'
]
});
// 遍历 AST
traverse
(
ast
,
{
ImportDeclaration
:
({
node
})
=>
{
// 获取 import from 地址
const
{
value
}
=
node
.
source
;
const
jsFile
=
transformScript
(
dirName
,
value
,
this
.
existsSync
);
if
(
jsFile
)
{
deps
.
push
(
jsFile
);
}
},
Property
:
(
nodePath
)
=>
{
const
parentPath
=
nodePath
.
parentPath
;
const
callee
=
parentPath
&&
parentPath
.
parent
&&
parentPath
.
parent
.
callee
;
if
(
!
callee
||
callee
.
name
!==
'
Component
'
)
{
return
;
}
const
relationsNodes
=
nodePath
.
container
.
filter
(
item
=>
item
.
key
.
name
===
'
relations
'
);
if
(
!
relationsNodes
.
length
)
{
return
;
}
const
relationsNode
=
relationsNodes
[
0
];
const
propertyNodes
=
relationsNode
.
value
.
properties
||
[];
let
allRelationsComponents
=
propertyNodes
.
map
(
filePathNode
=>
{
if
(
!
filePathNode
.
key
.
value
)
{
return
''
;
}
return
path
.
resolve
(
dirName
,
filePathNode
.
key
.
value
);
});
allRelationsComponents
=
allRelationsComponents
.
filter
(
item
=>
item
);
allRelationsComponents
.
forEach
(
component
=>
{
MpComponentFileExtension
.
forEach
((
ext
)
=>
{
const
file
=
this
.
addExtension
(
component
,
ext
);
if
(
this
.
existsSync
(
file
))
{
deps
.
push
(
file
);
}
});
});
},
ExportNamedDeclaration
:
({
node
})
=>
{
if
(
!
node
.
source
)
{
return
;
}
// 获取 export from 地址
const
{
value
}
=
node
.
source
;
const
jsFile
=
transformScript
(
dirName
,
value
,
this
.
existsSync
);
if
(
jsFile
)
{
deps
.
push
(
jsFile
);
}
},
CallExpression
:
({
node
})
=>
{
if
((
node
.
callee
.
name
&&
node
.
callee
.
name
===
'
require
'
)
&&
node
.
arguments
.
length
>=
1
)
{
// 获取 require 地址
const
[{
value
}]
=
node
.
arguments
;
const
jsFile
=
transformScript
(
dirName
,
value
,
this
.
existsSync
);
if
(
jsFile
)
{
deps
.
push
(
jsFile
);
}
}
},
});
return
deps
;
}
}
module
.
exports
=
CollectDependency
;
\ No newline at end of file
packages/uni-mp-weixin/lib/analyze-wxcomponent-dependency/constant.js
0 → 100644
浏览文件 @
65049f2f
const
WxMpFileExtension
=
{
js
:
'
js
'
,
json
:
'
json
'
,
wxml
:
'
wxml
'
,
wxss
:
'
wxss
'
,
};
module
.
exports
=
{
MpComponentFileExtension
:
Object
.
values
(
WxMpFileExtension
),
WxMpFileExtension
:
Object
.
assign
({},
WxMpFileExtension
,
{
'
wxs
'
:
'
wxs
'
}),
};
packages/uni-mp-weixin/lib/analyze-wxcomponent-dependency/index.js
0 → 100644
浏览文件 @
65049f2f
const
fs
=
require
(
'
fs-extra
'
);
const
path
=
require
(
'
path
'
);
const
{
addExtension
}
=
require
(
'
./utils.js
'
);
const
{
MpComponentFileExtension
,
WxMpFileExtension
}
=
require
(
'
./constant.js
'
);
const
CollectDependency
=
require
(
'
./collect-dependency.js
'
);
const
extToCollectMethodName
=
{
[
WxMpFileExtension
.
js
]:
'
getJsDeps
'
,
[
WxMpFileExtension
.
wxs
]:
'
getJsDeps
'
,
[
WxMpFileExtension
.
wxss
]:
'
getWxCssDeps
'
,
[
WxMpFileExtension
.
wxml
]:
'
getWxHtmlDeps
'
,
[
WxMpFileExtension
.
json
]:
'
getJsonDeps
'
,
};
class
Depend
{
constructor
(
context
,
readFileSync
,
existsSync
)
{
this
.
existsSync
=
existsSync
||
fs
.
existsSync
.
bind
(
fs
);
this
.
readFileSync
=
readFileSync
||
fs
.
readFileSync
.
bind
(
fs
);
this
.
componentLogicFiles
=
new
Set
();
this
.
files
=
new
Set
();
this
.
context
=
context
;
this
.
allComponents
=
new
Set
();
this
.
collectDependency
=
new
CollectDependency
(
context
,
this
.
readFileSync
,
this
.
existsSync
,
this
.
addExtension
.
bind
(
this
));
}
addExtension
(
filePath
,
ext
=
''
)
{
if
(
ext
===
WxMpFileExtension
.
json
)
{
this
.
allComponents
.
add
(
filePath
);
}
return
`
${
filePath
}
.
${
ext
}
`
;
}
// 将文件添加到树中
addToTree
(
filePath
)
{
filePath
=
path
.
resolve
(
filePath
);
if
(
this
.
files
.
has
(
filePath
))
{
return
;
}
this
.
files
.
add
(
filePath
);
const
deps
=
this
.
getDeps
(
filePath
)
||
[];
deps
.
forEach
(
dep
=>
this
.
addToTree
(
dep
));
}
getDeps
(
filePath
)
{
const
extension
=
path
.
extname
(
filePath
).
slice
(
1
);
const
collectMethod
=
extToCollectMethodName
[
extension
];
if
(
!
collectMethod
)
{
return
[];
}
const
files
=
this
.
collectDependency
[
collectMethod
](
filePath
);
const
logicFiles
=
files
.
filter
(
filePath
=>
filePath
.
endsWith
(
WxMpFileExtension
.
js
));
logicFiles
.
forEach
(
logicFile
=>
this
.
componentLogicFiles
.
add
(
logicFile
));
return
files
;
}
getDepsByPageOrComponentPath
(
absPath
)
{
MpComponentFileExtension
.
forEach
(
ext
=>
{
const
filePath
=
this
.
addExtension
(
absPath
,
ext
);
if
(
this
.
existsSync
(
filePath
))
{
if
(
ext
===
WxMpFileExtension
.
js
)
{
this
.
componentLogicFiles
.
add
(
filePath
);
}
this
.
addToTree
(
filePath
);
}
});
}
getDepsByComponents
(
components
)
{
components
.
forEach
(
page
=>
{
// 获取绝对地址
const
absPath
=
path
.
join
(
this
.
context
,
page
);
this
.
getDepsByPageOrComponentPath
(
absPath
);
});
return
this
.
files
;
}
}
module
.
exports
=
Depend
;
packages/uni-mp-weixin/lib/analyze-wxcomponent-dependency/utils.js
0 → 100644
浏览文件 @
65049f2f
const
path
=
require
(
'
path
'
);
const
fs
=
require
(
'
fs-extra
'
);
module
.
exports
=
{
resolveToContext
(
dirName
,
relativePath
,
context
)
{
if
(
relativePath
.
startsWith
(
'
/
'
))
{
return
`
${
context
}${
relativePath
}
`
;
}
return
path
.
resolve
(
dirName
,
relativePath
);
},
// 获取某个路径的脚本文件
transformScript
:
function
(
url
,
value
,
existsSync
=
fs
.
existsSync
)
{
url
=
`
${
url
}
/
${
value
}
`
;
const
ext
=
path
.
extname
(
url
);
// 如果存在后缀,表示当前已经是一个文件
const
exts
=
[
'
.js
'
,
'
.wxs
'
];
if
(
exts
.
includes
(
ext
)
&&
existsSync
(
url
))
{
return
url
;
}
// a/b/c => a/b/c.js
const
jsFile
=
url
+
'
.js
'
;
if
(
existsSync
(
jsFile
))
{
return
jsFile
;
}
// a/b/c => a/b/c.js
const
wxsFile
=
url
+
'
.wxs
'
;
if
(
existsSync
(
wxsFile
))
{
return
wxsFile
;
}
// a/b/c => a/b/c/index.js
const
jsIndexFile
=
path
.
join
(
url
,
'
index.js
'
);
if
(
existsSync
(
jsIndexFile
))
{
return
jsIndexFile
;
}
const
wxsIndexFile
=
path
.
join
(
url
,
'
index.wxs
'
);
if
(
existsSync
(
wxsIndexFile
))
{
return
wxsIndexFile
;
}
return
null
;
}
};
packages/uni-mp-weixin/lib/createIndependentPlugin.js
0 → 100644
浏览文件 @
65049f2f
const
AddShareAbilityToRuntimePlugin
=
require
(
'
./independent-plugins/add-share-ability-to-runtime-plugin
'
);
const
GenerateIndepndentEntryPlugin
=
require
(
'
./independent-plugins/generate-indepndent-entry-plugin
'
);
const
InjectEntryJsToIndependentPlugin
=
require
(
'
./independent-plugins/inject-entry-to-independent-plugin
'
);
const
InjectMainCssToIndependentCssPlugin
=
require
(
'
./independent-plugins/inject-main-css-to-independent-plugin
'
);
const
RunDefaultAppPlugin
=
require
(
'
./independent-plugins/run-default-app-plugin
'
);
const
SplitIndependentChunksPlugin
=
require
(
'
./independent-plugins/split-independent-chunks-plugin
'
);
const
ModifyUniAppWebpackConfigPlugin
=
require
(
'
./independent-plugins/modify-uniapp-webpack-config-Plugin
'
);
const
AddWxMpRuntimePlugin
=
require
(
'
./independent-plugins/add-weixin-mp-runtime-plugin
'
);
const
AppInterceptorPlugin
=
require
(
'
./independent-plugins/app-interceptor-plugin
'
);
module
.
exports
=
function
createIndependentPlugins
()
{
const
manifestConfig
=
process
.
UNI_MANIFEST
;
const
weixinConfig
=
manifestConfig
[
'
mp-weixin
'
];
const
independentSwitch
=
!!
weixinConfig
.
independentSwitch
;
if
(
!
independentSwitch
)
return
[];
// 支持构造微信小程序的独立分包
const
independentPlugins
=
[
new
SplitIndependentChunksPlugin
(),
new
ModifyUniAppWebpackConfigPlugin
(),
// 修改 webpack配置
new
AddShareAbilityToRuntimePlugin
(),
// 保证独立分包和主包使用的相同的runtime.js
new
GenerateIndepndentEntryPlugin
(),
// 生成独立分包执行入口文件(代替app.js
new
InjectEntryJsToIndependentPlugin
(),
// 为独立分包注入执行入口
new
RunDefaultAppPlugin
(),
// 确保app.js中的App()被执行一次
// 独立分包中 App,getApp 调用拦截
new
AddWxMpRuntimePlugin
(),
new
AppInterceptorPlugin
()
];
const
insertAppCssToIndependentSwitch
=
!!
weixinConfig
.
insertAppCssToIndependentSwitch
;
if
(
insertAppCssToIndependentSwitch
)
{
// 需要在 cacheSet 后面
independentPlugins
.
push
(
new
InjectMainCssToIndependentCssPlugin
());
// 目前只对页面注入了,组件未注入
}
return
independentPlugins
;
};
\ No newline at end of file
packages/uni-mp-weixin/lib/independent-plugins/add-share-ability-to-runtime-plugin.js
0 → 100644
浏览文件 @
65049f2f
const
{
parse
}
=
require
(
'
@babel/parser
'
);
const
template
=
require
(
'
@babel/template
'
);
const
generator
=
require
(
'
@babel/generator
'
);
const
traverse
=
require
(
'
@babel/traverse
'
);
const
{
generateAsset
}
=
require
(
'
./utils
'
);
// 【修改】runtime.js => 全局共享 global.webpackJsonP
class
AddShareAbilityToRuntimePlugin
{
apply
(
compiler
)
{
compiler
.
hooks
.
emit
.
tapPromise
(
'
AddShareAbilityToRuntimePlugin
'
,
compilation
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
try
{
// debugger
// 修改 runtime.js
const
runtimeChunkName
=
'
common/runtime.js
'
;
const
commonRuntimeInfo
=
compilation
.
assets
[
runtimeChunkName
];
if
(
!
commonRuntimeInfo
)
{
resolve
();
return
;
}
const
commonRuntimeStrContent
=
commonRuntimeInfo
.
source
();
const
commonRuntimeAst
=
parse
(
commonRuntimeStrContent
);
traverse
.
default
(
commonRuntimeAst
,
{
AssignmentExpression
(
nodePath
)
{
try
{
const
leftNode
=
nodePath
.
node
.
left
;
if
(
leftNode
.
type
===
'
MemberExpression
'
&&
leftNode
.
object
&&
leftNode
.
property
)
{
if
(
leftNode
.
object
.
name
===
'
global
'
&&
leftNode
.
property
.
value
===
'
webpackJsonp
'
)
{
const
insertCode
=
'
if(global.webpackJsonp){ return };
'
;
const
astNode
=
template
.
statements
(
insertCode
)();
const
blockNode
=
nodePath
.
scope
.
block
;
blockNode
.
body
.
body
.
unshift
(...
astNode
);
nodePath
.
stop
();
}
}
}
catch
(
e
)
{
console
.
error
(
'
independent.error
'
,
'
ShareRuntimeChunkPlugin
'
,
e
);
}
},
});
const
runtimeSource
=
generator
.
default
(
commonRuntimeAst
).
code
;
const
runtimeAsset
=
generateAsset
(
runtimeSource
);
compilation
.
assets
[
runtimeChunkName
]
=
runtimeAsset
;
Object
.
values
(
process
.
UNI_SUBPACKAGES
).
forEach
(
pkgInfo
=>
{
if
(
pkgInfo
.
independent
)
{
compilation
.
assets
[
`
${
pkgInfo
.
root
}
/
${
runtimeChunkName
}
`
]
=
runtimeAsset
;
}
});
resolve
();
}
catch
(
e
)
{
console
.
error
(
'
independent.error
'
,
'
AddShareAbilityToRuntimePlugin
'
,
e
);
reject
(
e
);
}
});
});
}
}
module
.
exports
=
AddShareAbilityToRuntimePlugin
;
\ No newline at end of file
packages/uni-mp-weixin/lib/independent-plugins/add-weixin-mp-runtime-plugin.js
0 → 100644
浏览文件 @
65049f2f
const
fs
=
require
(
'
fs-extra
'
);
const
path
=
require
(
'
path
'
);
const
{
generateAsset
}
=
require
(
'
./utils
'
);
const
t
=
require
(
'
@babel/types
'
);
const
babelGenerator
=
require
(
'
@babel/generator
'
);
const
babelParser
=
require
(
'
@babel/parser
'
);
const
{
default
:
babelTraverse
}
=
require
(
'
@babel/traverse
'
);
const
getWxMpRuntime
=
require
(
'
../runtime/index
'
);
// TODO 这个工作应该放在loader中做,后续优化
class
AddWxMpRuntimePlugin
{
apply
(
compiler
)
{
compiler
.
hooks
.
emit
.
tapPromise
(
'
AddWxMpRuntimePlugin
'
,
compilation
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
try
{
// 收集独立分包路径下面的所有js文件
// js文件都存储在 compilation.assets中 , 因为需要注入 require(`${pkgRoot/common/index.js}`)
const
thisCompilationAssets
=
compilation
.
assets
;
const
independentPkgsInfo
=
Object
.
values
(
process
.
UNI_SUBPACKAGES
).
filter
(
info
=>
info
.
independent
)
||
[];
const
independentPkgRoots
=
independentPkgsInfo
.
map
(
info
=>
`
${
info
.
root
}
`
);
if
(
!
independentPkgRoots
.
length
)
{
resolve
();
}
const
mpRuntimePath
=
getWxMpRuntime
();
const
wxMpRuntimeContent
=
fs
.
readFileSync
(
mpRuntimePath
,
'
utf8
'
);
const
ast
=
babelParser
.
parse
(
wxMpRuntimeContent
,
{
sourceType
:
'
module
'
,
plugins
:
[
'
classProperties
'
],
});
babelTraverse
(
ast
,
{
VariableDeclaration
(
path
)
{
const
v
=
path
.
node
.
declarations
[
0
];
const
name
=
v
.
id
.
name
;
const
value
=
v
.
init
;
if
(
name
===
'
independentRoots
'
&&
t
.
isArrayExpression
(
value
))
{
value
.
elements
=
independentPkgRoots
.
map
(
pkgRoot
=>
t
.
StringLiteral
(
pkgRoot
));
}
},
});
const
{
code
}
=
babelGenerator
.
default
(
ast
);
const
runtimeAssetsInfo
=
generateAsset
(
code
);
const
mpRuntimeRelativePath
=
'
common/wxMpRuntime.js
'
;
// 处理app.js
const
appJsName
=
'
app.js
'
;
thisCompilationAssets
[
mpRuntimeRelativePath
]
=
runtimeAssetsInfo
;
const
assetInfo
=
thisCompilationAssets
[
appJsName
];
if
(
!
assetInfo
)
{
return
resolve
();
}
const
content
=
assetInfo
.
source
();
thisCompilationAssets
[
appJsName
]
=
generateAsset
(
`require('./common/wxMpRuntime.js');
${
content
}
`
);
// 处理独立分包
independentPkgRoots
.
forEach
(
pkgRoot
=>
{
thisCompilationAssets
[
`
${
pkgRoot
}
/
${
mpRuntimeRelativePath
}
`
]
=
runtimeAssetsInfo
;
const
entryJsName
=
`
${
pkgRoot
}
/common/index.js`
;
const
assetInfo
=
thisCompilationAssets
[
entryJsName
];
let
content
=
assetInfo
.
source
();
content
=
generateAsset
(
`require('./wxMpRuntime.js');
${
content
}
`
);
thisCompilationAssets
[
entryJsName
]
=
content
;
});
resolve
();
}
catch
(
e
)
{
console
.
error
(
'
AddWxMpRuntimePlugin
'
,
e
);
reject
(
e
);
}
});
});
}
}
module
.
exports
=
AddWxMpRuntimePlugin
;
packages/uni-mp-weixin/lib/independent-plugins/app-interceptor-plugin.js
0 → 100644
浏览文件 @
65049f2f
const
t
=
require
(
'
@babel/types
'
);
const
babelTraverse
=
require
(
'
@babel/traverse
'
).
default
;
const
babelParser
=
require
(
'
@babel/parser
'
);
const
babelGenerator
=
require
(
'
@babel/generator
'
);
const
{
generateAsset
}
=
require
(
'
./utils
'
);
const
{
collectIndependentJsAssets
}
=
require
(
'
./optimize-components-position/util
'
);
const
visitor
=
{
CallExpression
(
path
)
{
const
funNode
=
path
.
node
;
// https://developers.weixin.qq.com/miniprogram/dev/reference/api/getApp.html
// FIX: 目前getApp仅支持一个参数(allowDefault),如果后面增加更多的参数以下逻辑需要修改
// 增减判断是否有该参数逻辑
if
(
t
.
isIdentifier
(
path
.
node
.
callee
))
{
if
(
funNode
.
callee
.
name
===
'
getApp
'
&&
funNode
.
arguments
.
length
===
0
)
{
funNode
.
callee
=
t
.
MemberExpression
(
t
.
Identifier
(
'
(global.global || global)
'
),
t
.
Identifier
(
'
getApp
'
));
}
else
if
(
funNode
.
callee
.
name
===
'
App
'
)
{
funNode
.
callee
=
t
.
MemberExpression
(
t
.
Identifier
(
'
(global.global || global)
'
),
t
.
Identifier
(
'
App
'
));
}
}
},
};
// 关键:需要在在整个emit阶段的最后(compilation.assets['/pages/chat-im/wxcomponents/...']
class
AppInterceptorPlugin
{
apply
(
compiler
)
{
compiler
.
hooks
.
emit
.
tapPromise
(
'
AppInterceptorPlugin
'
,
compilation
=>
{
return
new
Promise
(
resolve
=>
{
// 收集独立分包路径下面的所有js文件
// js文件都存储在 compilation.assets中 , 因为需要注入 require(`${pkgRoot/common/index.js}`)
const
thisCompilationAssets
=
compilation
.
assets
;
const
independentJsAssets
=
collectIndependentJsAssets
(
thisCompilationAssets
);
independentJsAssets
.
forEach
(({
jsAssets
})
=>
{
jsAssets
.
forEach
(
jsAssetName
=>
{
if
(
jsAssetName
.
endsWith
(
'
common/wxMpRuntime.js
'
))
{
return
;
}
const
assetInfo
=
thisCompilationAssets
[
jsAssetName
];
let
assetSource
=
assetInfo
.
source
();
// 有部分js文件在这里是Buffer类型
if
(
assetSource
instanceof
Buffer
)
{
assetSource
=
assetSource
.
toString
();
}
const
ast
=
babelParser
.
parse
(
assetSource
,
{
sourceType
:
'
module
'
,
plugins
:
[
'
classProperties
'
],
});
babelTraverse
(
ast
,
visitor
);
const
{
code
}
=
babelGenerator
.
default
(
ast
);
thisCompilationAssets
[
jsAssetName
]
=
generateAsset
(
code
);
}
);
});
resolve
();
});
});
}
}
module
.
exports
=
AppInterceptorPlugin
;
packages/uni-mp-weixin/lib/independent-plugins/generate-indepndent-entry-plugin.js
0 → 100644
浏览文件 @
65049f2f
const
crypto
=
require
(
'
crypto
'
);
const
{
generateAsset
}
=
require
(
'
./utils
'
);
const
emitFileCaches
=
{};
function
md5
(
str
)
{
const
hash
=
crypto
.
createHash
(
'
md5
'
);
hash
.
update
(
str
);
return
hash
.
digest
(
'
hex
'
);
}
function
emitFile
(
filePath
,
source
,
compilation
)
{
const
emitFileMD5
=
md5
(
filePath
+
source
);
if
(
emitFileCaches
[
filePath
]
!==
emitFileMD5
)
{
emitFileCaches
[
filePath
]
=
emitFileMD5
;
compilation
.
assets
[
filePath
]
=
generateAsset
(
source
);
}
}
// 为独立分包【生成】入口执行文件,代替主包中的app.js
class
GenerateIndepndentEntryPlugin
{
apply
(
compiler
)
{
compiler
.
hooks
.
emit
.
tapPromise
(
'
GenerateIndepndentEntryPlugin
'
,
compilation
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
try
{
// debugger
const
independentPkgs
=
Object
.
values
(
process
.
UNI_SUBPACKAGES
).
filter
(
subPkgItem
=>
subPkgItem
.
independent
)
||
[];
const
independentEntry
=
independentPkgs
.
map
(
independentPkgItem
=>
{
return
{
file
:
`
${
independentPkgItem
.
root
}
/common/index.js`
,
source
:
`require('runtime.js');require('library.js');require('vendor.js');require('main.js');`
,
};
});
independentEntry
.
forEach
(({
file
,
source
})
=>
emitFile
(
file
,
source
,
compilation
));
resolve
();
}
catch
(
e
)
{
console
.
error
(
'
independent.error
'
,
'
GenerateIndepndentEntryPlugin
'
,
e
);
reject
(
e
);
}
});
});
}
}
module
.
exports
=
GenerateIndepndentEntryPlugin
;
\ No newline at end of file
packages/uni-mp-weixin/lib/independent-plugins/inject-entry-to-independent-plugin.js
0 → 100644
浏览文件 @
65049f2f
const
path
=
require
(
'
path
'
);
const
{
normalizePath
,
generateAsset
}
=
require
(
'
./utils
'
);
// TODO 换个位置?
// 独立分包的页面或者组件中【注入】 require('index.js') => 代替 app.js 功效
class
InjectEntryJsToIndependentPlugin
{
apply
(
compiler
)
{
compiler
.
hooks
.
emit
.
tapPromise
(
'
InjectEntryJsToIndependentPlugin
'
,
compilation
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
try
{
// debugger
Object
.
keys
(
process
.
UNI_SUBPACKAGES
).
forEach
(
root
=>
{
const
pkgInfo
=
process
.
UNI_SUBPACKAGES
[
root
];
if
(
!
pkgInfo
.
independent
)
return
;
const
subPackageVendorPath
=
normalizePath
(
path
.
join
(
root
,
'
common
'
));
Object
.
keys
(
compilation
.
assets
).
forEach
(
name
=>
{
// 是个js文件都需要加上(不限制组件或者页面
if
(
path
.
extname
(
name
)
===
'
.js
'
&&
name
.
startsWith
(
root
+
'
/
'
)
&&
!
name
.
startsWith
(
subPackageVendorPath
))
{
const
originalSource
=
compilation
.
assets
[
name
].
source
();
const
entryRuntime
=
normalizePath
(
path
.
relative
(
path
.
dirname
(
name
),
subPackageVendorPath
));
const
source
=
`require('
${
entryRuntime
}
/index.js');
${
originalSource
}
`
;
compilation
.
assets
[
name
]
=
generateAsset
(
source
);
}
});
});
resolve
();
}
catch
(
e
)
{
console
.
error
(
'
independent.error
'
,
'
InjectEntryJsToIndependentPlugin
'
,
e
);
reject
(
e
);
}
});
});
}
}
module
.
exports
=
InjectEntryJsToIndependentPlugin
;
\ No newline at end of file
packages/uni-mp-weixin/lib/independent-plugins/inject-main-css-to-independent-plugin.js
0 → 100644
浏览文件 @
65049f2f
const
fs
=
require
(
'
fs-extra
'
);
const
path
=
require
(
'
path
'
);
const
{
generateAsset
}
=
require
(
'
./utils
'
);
const
{
getNewComponentPathInIndependentPkg
,
getJsonByPageOrComponentPath
}
=
require
(
'
./optimize-components-position/util
'
);
const
{
getIndependentPkgRoots
,
getIndependentEntryPages
}
=
require
(
'
@dcloudio/uni-mp-weixin/lib/independent-plugins/optimize-components-position/util
'
);
function
generateCssSource
(
pkgMainCssPath
,
pkgLibraryCssPath
,
wxssSourceInfo
)
{
const
platforms
=
[
'
mp-weixin
'
,
'
mp-qq
'
,
'
mp-toutiao
'
];
const
presetStyle
=
platforms
.
includes
(
process
.
env
.
UNI_PLATFORM
)
?
'
[data-custom-hidden="true"],[bind-data-custom-hidden="true"]{display: none !important;}
'
:
''
;
return
`@import '/
${
pkgMainCssPath
}
';
@import '/
${
pkgLibraryCssPath
}
';
${
wxssSourceInfo
.
source
()}
${
presetStyle
}
`
;
}
function
copyWeuiCssToIndependent
(
independentRoot
)
{
const
weuiCssRelativePath
=
'
wxcomponents/weui-miniprogram/weui-wxss/dist/style/weui.wxss
'
;
const
fromPath
=
path
.
resolve
(
process
.
env
.
UNI_INPUT_DIR
,
weuiCssRelativePath
);
const
toPath
=
path
.
resolve
(
process
.
env
.
UNI_OUTPUT_DIR
,
`
${
independentRoot
}
/
${
weuiCssRelativePath
}
`
);
if
(
fs
.
existsSync
(
fromPath
))
{
fs
.
copySync
(
fromPath
,
toPath
);
return
true
;
}
else
{
console
.
warn
(
'
添加weui组件库到wxcomponents目录下
'
);
}
return
false
;
}
function
tryInsertWeuiCss
(
independentRoot
,
originalWxssStr
)
{
const
manifestConfig
=
process
.
UNI_MANIFEST
;
const
weixinConfig
=
manifestConfig
[
'
mp-weixin
'
]
||
{};
const
independentSwitch
=
!!
weixinConfig
.
independentSwitch
;
// 如果使用了weui,则需要注入weui样式
const
useExtendedWeUi
=
!!
(
weixinConfig
.
useExtendedLib
||
{}).
weui
;
// 复制
const
successOrNot
=
copyWeuiCssToIndependent
(
independentRoot
);
const
insertStr
=
`@import '/
${
independentRoot
}
/wxcomponents/weui-miniprogram/weui-wxss/dist/style/weui.wxss'`
;
return
(
successOrNot
&&
useExtendedWeUi
)
?
`
${
insertStr
}
;
${
originalWxssStr
}
`
:
originalWxssStr
;
}
// 独立分包页面不受app.wxss影响
// 独立分包中所有的页面需要导入main.wxss
class
InjectMainCssToIndependentCssPlugin
{
apply
(
compiler
)
{
compiler
.
hooks
.
emit
.
tapPromise
(
'
InjectMainCssToIndependentCssPlugin
'
,
compilation
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
try
{
// TODO 判断主包中 common/main.wxss是否存在,不存在直接return
const
thisCompilationAssets
=
compilation
.
assets
;
const
indendentRoots
=
getIndependentPkgRoots
();
indendentRoots
.
forEach
(
indendentRoot
=>
{
const
pkgMainCssPath
=
`
${
indendentRoot
}
/common/main.wxss`
;
const
pkgLibraryCssPath
=
`
${
indendentRoot
}
/common/library.wxss`
;
const
pkgPagesPath
=
getIndependentEntryPages
(
indendentRoot
);
// const cacheSet = new Set();
// 获取所有页面和组件
// findAllPagesAndComponentsByIndependentRoot(thisCompilationAssets, indendentRoot, pkgPagesPath, cacheSet);
// const allPagesAndCompoents = [...cacheSet];
// 关键,app.wxss和页面.wxss 对组件的影响是一样的。只需要注入到页面即可
// 记:Component构造页面的化,不需要注入app.wxss。uniapp不存在该情况即页面均是通过Page构造,因此向页面注入
// https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html#%E7%BB%84%E4%BB%B6%E6%A0%B7%E5%BC%8F%E9%9A%94%E7%A6%BB
pkgPagesPath
.
forEach
(
pageAndComponentPath
=>
{
if
(
pageAndComponentPath
.
startsWith
(
'
/
'
))
{
pageAndComponentPath
=
pageAndComponentPath
.
substring
(
1
);
}
if
(
pageAndComponentPath
.
indexOf
(
'
weui-miniprogra
'
)
>=
0
)
{
return
;
}
const
pageWxssPath
=
`
${
pageAndComponentPath
}
.wxss`
;
const
wxssSourceInfo
=
thisCompilationAssets
[
pageWxssPath
];
if
(
!
wxssSourceInfo
)
{
// 有可能确实没有产出.wxss文件
console
.
log
(
'
invalid wxssSourceInfo
'
,
pageAndComponentPath
);
return
;
}
let
wxssSource
=
generateCssSource
(
pkgMainCssPath
,
pkgLibraryCssPath
,
wxssSourceInfo
);
wxssSource
=
tryInsertWeuiCss
(
indendentRoot
,
wxssSource
);
thisCompilationAssets
[
pageWxssPath
]
=
generateAsset
(
wxssSource
);
});
});
resolve
();
}
catch
(
e
)
{
console
.
error
(
'
independent.error
'
,
'
InjectMainCssToIndependentCssPlugin
'
,
e
);
reject
(
e
);
}
});
});
}
}
module
.
exports
=
InjectMainCssToIndependentCssPlugin
;
//
// function findAllPagesAndComponentsByIndependentRoot (thisCompilationAssets, independentRoot, pageOrComponents = [], cacheSet = new Set()) {
// pageOrComponents.forEach(pageOrComponentPath => {
// // 防止递归
// const recured = cacheSet.has(pageOrComponentPath);
// if (recured) return;
// cacheSet.add(pageOrComponentPath);
//
// pageOrComponentPath = getNewComponentPathInIndependentPkg(independentRoot, pageOrComponentPath);
// if (pageOrComponentPath.startsWith('/')) {
// pageOrComponentPath = pageOrComponentPath.substring(1);
// }
// const pathWithSuffix = `${pageOrComponentPath}.json`;
// const assetInfo = thisCompilationAssets[pathWithSuffix]; // 原生组件的json文件在copy时保存到了 compilationAssets
// const jsonObj = assetInfo && JSON.parse(assetInfo.source().toString());
//
// if (!jsonObj) {
// console.error('independent.error.recurIndependentJson', pageOrComponentPath);
// return;
// }
//
// const usingComponents = Object.values(jsonObj.usingComponents || {});
// findAllPagesAndComponentsByIndependentRoot(thisCompilationAssets, independentRoot, usingComponents, cacheSet);
// });
// }
packages/uni-mp-weixin/lib/independent-plugins/insert-weui-css-to-independent-plugin.js
0 → 100644
浏览文件 @
65049f2f
@
import
'
weui-miniprogram/weui-wxss/dist/style/weui.wxss
'
;
class
InjectWeuiCssToIndependentPlugin
{
apply
(
compiler
)
{
compiler
.
hooks
.
emit
.
tapPromise
(
'
InjectWeuiCssToIndependentPlugin
'
,
compilation
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
try
{
const
thisCompilationAssets
=
compilation
.
assets
;
resolve
();
}
catch
(
e
)
{
console
.
error
(
'
independent.error
'
,
'
InjectWeuiCssToIndependentPlugin
'
,
e
);
reject
(
e
);
}
});
});
}
}
module
.
exports
=
InjectMainCssToIndepe
;
\ No newline at end of file
packages/uni-mp-weixin/lib/independent-plugins/modify-uniapp-webpack-config-Plugin.js
0 → 100644
浏览文件 @
65049f2f
class
ModifyUniAppWebpackConfigPlugin
{
apply
(
compiler
)
{
compiler
.
hooks
.
environment
.
tap
(
'
ModifyUniAppWebpackConfigPlugin
'
,
()
=>
{
// 不注册webpack内置的splitchunksplugin
delete
compiler
.
options
.
optimization
.
splitChunks
;
});
}
}
module
.
exports
=
ModifyUniAppWebpackConfigPlugin
;
packages/uni-mp-weixin/lib/independent-plugins/optimize-components-position/analyze.js
0 → 100644
浏览文件 @
65049f2f
const
{
wxComponentsStr
}
=
require
(
'
./constant
'
);
const
fs
=
require
(
'
fs-extra
'
);
const
path
=
require
(
'
path
'
);
const
{
generateAsset
}
=
require
(
'
./util
'
);
module
.
exports
=
class
Analyze
{
constructor
(
emitFileMap
,
AnalyzeWxcomponentDependency
,
compilation
)
{
this
.
emitFileMap
=
emitFileMap
;
this
.
compilation
=
compilation
;
this
.
AnalyzeWxcomponentDependency
=
AnalyzeWxcomponentDependency
;
}
readFileSync
(
file
)
{
if
(
!
file
.
startsWith
(
process
.
env
.
UNI_INPUT_DIR
))
{
file
=
path
.
resolve
(
process
.
env
.
UNI_INPUT_DIR
,
file
.
substring
(
1
,
Number
.
MAX_SAFE_INTEGER
));
}
const
wxComponentAbsPath
=
`
${
process
.
env
.
UNI_INPUT_DIR
}
/
${
wxComponentsStr
}
`
;
if
(
file
.
startsWith
(
wxComponentAbsPath
))
{
return
fs
.
readFileSync
(
file
);
}
else
{
const
assets
=
this
.
compilation
.
assets
;
const
pathWithoutRelative
=
path
.
resolve
(
file
);
const
relativePath
=
path
.
relative
(
process
.
env
.
UNI_INPUT_DIR
,
pathWithoutRelative
);
const
memoryFileInfo
=
assets
[
relativePath
];
if
(
memoryFileInfo
)
{
return
memoryFileInfo
.
source
();
}
// 针对json文件,当前由 generate-json 发出,所以资源尚未同步到compilations.assets中
return
JSON
.
stringify
(
this
.
emitFileMap
.
get
(
relativePath
));
}
}
existsSync
(
file
)
{
// 类似补丁吧,传过来的路径可能不是/Users
if
(
!
file
.
startsWith
(
process
.
env
.
UNI_INPUT_DIR
))
{
file
=
path
.
resolve
(
process
.
env
.
UNI_INPUT_DIR
,
file
.
substring
(
1
));
}
const
wxComponentAbsPath
=
`
${
process
.
env
.
UNI_INPUT_DIR
}
/
${
wxComponentsStr
}
`
;
if
(
file
.
startsWith
(
wxComponentAbsPath
))
{
return
fs
.
existsSync
(
file
);
}
// vue组件的js文件忽略
// if (file.endsWith('.js')) {
// return false;
// }
const
assets
=
this
.
compilation
.
assets
;
const
pathWithoutRelative
=
path
.
resolve
(
file
);
const
relativePath
=
path
.
relative
(
process
.
env
.
UNI_INPUT_DIR
,
pathWithoutRelative
);
// 针对json文件,当前由 generate-json 发出,所以资源尚未同步到compilations.assets中
if
(
relativePath
.
endsWith
(
'
.json
'
))
{
return
!!
this
.
emitFileMap
.
get
(
relativePath
);
}
return
!!
assets
[
relativePath
];
}
findAllWxComponentsDependency
(
componentsPath
,
useMemoryCache
=
false
)
{
const
context
=
process
.
env
.
UNI_INPUT_DIR
;
let
instance
;
if
(
useMemoryCache
)
{
instance
=
new
this
.
AnalyzeWxcomponentDependency
(
context
,
this
.
readFileSync
.
bind
(
this
),
this
.
existsSync
.
bind
(
this
));
}
else
{
instance
=
new
this
.
AnalyzeWxcomponentDependency
(
context
);
}
return
{
dependFiles
:
instance
.
getDepsByComponents
(
componentsPath
),
allComponents
:
[...
instance
.
allComponents
],
};
}
copyWxComponent
(
pkgRoot
,
originalFilePath
,
targetPath
)
{
const
thisCompilationAssets
=
this
.
compilation
.
assets
;
const
suffix
=
path
.
extname
(
originalFilePath
);
if
(
!
[
'
.js
'
,
'
.json
'
,
'
.wxss
'
].
includes
(
suffix
))
{
return
fs
.
copySync
(
originalFilePath
,
targetPath
);
}
let
jsonSource
=
fs
.
readFileSync
(
originalFilePath
,
'
utf8
'
);
const
assetPath
=
path
.
relative
(
process
.
env
.
UNI_OUTPUT_DIR
,
targetPath
);
if
(
suffix
===
'
.js
'
)
{
// 计算到 root/common/index 的相对路径
const
relativeToDist
=
path
.
relative
(
path
.
dirname
(
assetPath
),
`
${
pkgRoot
}
/common/index.js`
);
jsonSource
=
`require('
${
relativeToDist
}
');
${
jsonSource
}
`
;
thisCompilationAssets
[
assetPath
]
=
generateAsset
(
jsonSource
);
}
// 后续需要更新组件引用路径,所以不采用文件复制方式
// json 后面需要修改包外组件引用路径:copy-outer-components-for-independent
// wxss 需要注入 全局样式:inject-main-css-to-independent-plugin
if
([
'
.json
'
,
'
.wxss
'
].
includes
(
suffix
))
{
thisCompilationAssets
[
assetPath
]
=
generateAsset
(
jsonSource
);
}
}
getDependFiles
(
obj
,
wxComponentFileDependencyCache
,
useMemoryCache
=
false
)
{
let
tmpAllComponents
=
[];
for
(
const
pkgRoot
in
obj
)
{
const
wxComponents
=
[...
obj
[
pkgRoot
]];
wxComponents
.
forEach
(
wxComponent
=>
{
if
(
!
wxComponentFileDependencyCache
[
wxComponent
])
{
const
{
dependFiles
,
allComponents
}
=
this
.
findAllWxComponentsDependency
([
wxComponent
],
useMemoryCache
);
tmpAllComponents
=
[...
tmpAllComponents
,
...
allComponents
];
wxComponentFileDependencyCache
[
wxComponent
]
=
dependFiles
||
[];
}
});
}
return
new
Set
(
tmpAllComponents
);
}
};
packages/uni-mp-weixin/lib/independent-plugins/optimize-components-position/constant.js
0 → 100644
浏览文件 @
65049f2f
module
.
exports
=
{
appJsonFileName
:
'
app.json
'
,
wxComponentsStr
:
'
wxcomponents
'
,
weuiComponentStr
:
'
weui-miniprogram
'
+
'
dd
'
,
mainPkgName
:
'
mainPkg
'
,
outerComponents
:
'
vueOuterComponents
'
,
componentType
:
{
wxComponent
:
'
wxComponent
'
,
vueComponent
:
'
vueComponent
'
,
unknown
:
'
unknown
'
}
};
packages/uni-mp-weixin/lib/independent-plugins/optimize-components-position/copy-outer-components-for-independent.js
0 → 100644
浏览文件 @
65049f2f
const
path
=
require
(
'
path
'
);
const
Analyze
=
require
(
'
./analyze
'
);
const
{
wxComponentsStr
,
outerComponents
,
weuiComponentStr
}
=
require
(
'
./constant
'
);
const
{
generateAsset
}
=
require
(
'
./util
'
);
const
{
collectAllOutSideComponentsMap
,
getIndependentPkgRoots
,
getIndependentEntryPages
,
getGlobalComponentKeyByGlobalComponentPath
,
copyAllWxComponentsFiles
,
collectPkgCopyFiles
,
getNewComponentPathInIndependentPkg
,
getJsonByPageOrComponentPath
}
=
require
(
'
./util
'
);
// 原则:原生组件不允许使用全局组件
// 忽略原生组件(wxComponents)使用全局组件的情况
function
recurIndependentJson
(
independentRoot
,
independentPages
,
sourceRepo
,
handler
,
cacheSet
=
new
Set
())
{
independentPages
.
forEach
(
independentPage
=>
{
// 避免无限递归
const
recured
=
cacheSet
.
has
(
independentPage
);
if
(
recured
)
return
;
cacheSet
.
add
(
independentPage
);
// 关键:映射到独立分包下面的组件路径
const
newComponentPath
=
getNewComponentPathInIndependentPkg
(
independentRoot
,
independentPage
);
const
{
content
:
jsonObj
,
fromAssetsFlag
}
=
getJsonByPageOrComponentPath
(
newComponentPath
,
sourceRepo
);
if
(
!
jsonObj
)
{
console
.
error
(
'
independent.error.recurIndependentJson
'
,
newComponentPath
);
return
;
}
// 处理 newComponentPath.json 中的包外组件路径
const
usingComponents
=
jsonObj
.
usingComponents
||
{};
for
(
let
componentKey
in
usingComponents
)
{
const
componentPath
=
usingComponents
[
componentKey
];
if
(
componentPath
.
indexOf
(
weuiComponentStr
)
>=
0
)
{
continue
;
}
handler
(
usingComponents
,
componentKey
);
recurIndependentJson
(
independentRoot
,
[
componentPath
],
sourceRepo
,
handler
,
cacheSet
);
}
if
(
fromAssetsFlag
)
{
sourceRepo
.
compilationAssets
[
`
${
newComponentPath
}
.json`
]
=
generateAsset
(
JSON
.
stringify
(
jsonObj
));
}
});
}
// TODO watch 只针对发生变化的文件
class
Index
extends
Analyze
{
init
()
{
const
emitFileMap
=
this
.
emitFileMap
;
const
independentRoots
=
getIndependentPkgRoots
();
const
outSideComponentsMap
=
{};
// 引用的包外组件(vue组件和原生组件)
independentRoots
.
forEach
(
independentRoot
=>
{
const
independentPages
=
getIndependentEntryPages
(
independentRoot
);
let
cacheSet
=
new
Set
();
let
cacheGlobalUsageMap
=
new
Map
();
// 收集包外组件
const
colletOuterCompos
=
independentPage
=>
collectAllOutSideComponentsMap
(
independentRoot
,
emitFileMap
,
independentPage
,
cacheSet
,
cacheGlobalUsageMap
);
independentPages
.
forEach
(
colletOuterCompos
);
// 如果是原生组件,则忽略wxComponents以外的组件
cacheSet
=
[...
cacheSet
].
filter
(
componentPath
=>
{
if
(
componentPath
.
startsWith
(
'
/
'
))
{
componentPath
=
componentPath
.
substring
(
1
);
}
const
isVueComponent
=
emitFileMap
.
get
(
`
${
componentPath
}
.json`
);
const
isWxComponent
=
componentPath
.
startsWith
(
`
${
wxComponentsStr
}
`
);
// TODO weui组件
return
!!
(
isVueComponent
||
isWxComponent
);
});
// 暂时只收集包外的vue组件和原生组件(wxComponents)
outSideComponentsMap
[
independentRoot
]
=
{
outerComponentSet
:
new
Set
(
cacheSet
),
globalComponentsMap
:
cacheGlobalUsageMap
};
});
// 独立分包使用到[全局组件]和[入口页面]作为[文件依赖分析]的入口
const
componentFileCache
=
{};
for
(
let
independentRoot
in
outSideComponentsMap
)
{
const
info
=
outSideComponentsMap
[
independentRoot
];
this
.
copyAndUpdateJson
(
independentRoot
,
info
,
componentFileCache
);
}
}
copyAndUpdateJson
(
independentRoot
,
info
,
componentFileCache
)
{
const
{
outerComponentSet
,
globalComponentsMap
}
=
info
;
this
.
getDependFiles
({
[
independentRoot
]:
outerComponentSet
},
componentFileCache
,
true
);
// 1. 先复制
this
.
copyOuterComponents
(
independentRoot
,
outerComponentSet
,
componentFileCache
);
// 2. 更新组件json中包外组件引用路径
this
.
updateIndependentJson
(
independentRoot
,
globalComponentsMap
);
}
updateIndependentJson
(
independentRoot
,
globalComponentsMap
)
{
// 1. 先添加全局组件依赖
this
.
addGlobalComponentReference
(
independentRoot
,
globalComponentsMap
);
// 2. 更新显示引用包外组件路径
this
.
updateOuterComponentReference
(
independentRoot
);
}
// pages/chat-im/vueOuterComponents/components/navigation-bar.json mini-icon引用出错?
// 先处理全局组件:将全局组件引用添加到json文件中
// 整体思路:
// 1. 在init函数中,收集了独立分包用到的所有全局组件(包括包外组件用到的全局组件),
// 2. 保存全局组件被那些页面或者组件使用
// 3. 复制包外组件(全局组件只是包外组件的一部分)
// 4. 由于独立分包不能使用全局组件,所以该方法将全局组件路径添加到独立分包下的组件或页面关联的json文件中,确保可以访问到。
addGlobalComponentReference
(
independentRoot
,
globalComponentsMap
)
{
const
globalComponentInfoMap
=
getGlobalComponentKeyByGlobalComponentPath
();
for
(
let
[
globalComponentPath
,
componentSetWhoUsedGlobalCompo
]
of
globalComponentsMap
)
{
// weui暂时先不处理
if
(
globalComponentPath
.
indexOf
(
weuiComponentStr
)
>=
0
)
{
continue
;
}
if
(
globalComponentPath
.
indexOf
(
weuiComponentStr
)
>=
0
)
{
continue
;
}
const
componentKey
=
globalComponentInfoMap
[
globalComponentPath
];
if
(
globalComponentPath
.
startsWith
(
'
/
'
))
{
globalComponentPath
=
globalComponentPath
.
substring
(
1
);
}
const
globalComponentReplacePath
=
getNewComponentPathInIndependentPkg
(
independentRoot
,
globalComponentPath
);
if
(
globalComponentReplacePath
===
globalComponentPath
)
return
;
// 理论上不会走
const
compilationAssets
=
this
.
compilation
.
assets
;
// pages均为vue文件
[...
componentSetWhoUsedGlobalCompo
].
forEach
(
componentWhoUsedGlobalCompo
=>
{
// 获取在 independentRoot 目录下的新路径(独立分包内引用的包外组件也有可能用到全局组件,获取该包外组件在独立分包内的新路径)
componentWhoUsedGlobalCompo
=
getNewComponentPathInIndependentPkg
(
independentRoot
,
componentWhoUsedGlobalCompo
);
// 获取该组件json文件内容
// 分包内的vue组件对应json存储在emitFileMap中
// 分包外vue组件由于前面的复制,内容保存在assets中
const
{
content
:
pageObj
,
fromAssetsFlag
// json内容是否来自assets(还可能来自emiFileMap)
}
=
getJsonByPageOrComponentPath
(
componentWhoUsedGlobalCompo
,
{
emitFileMap
:
this
.
emitFileMap
,
compilationAssets
});
const
usingComponents
=
pageObj
.
usingComponents
||
{};
// 如果没有同名标签,则使用全局组件(优先使用显示声明的标签-针对同名标签)
if
(
!
usingComponents
[
componentKey
])
{
usingComponents
[
componentKey
]
=
`/
${
globalComponentReplacePath
}
`
;
}
// 如果json内容来自emiFileMap(可能还没同步到assets上
// emitFileMap 后面会统一挂到assets上
if
(
!
fromAssetsFlag
)
return
;
compilationAssets
[
`
${
componentWhoUsedGlobalCompo
}
.json`
]
=
generateAsset
(
JSON
.
stringify
(
pageObj
));
});
}
}
updateOuterComponentReference
(
independentRoot
)
{
const
sourceRepo
=
{
emitFileMap
:
this
.
emitFileMap
,
compilationAssets
:
this
.
compilation
.
assets
};
const
independentPages
=
getIndependentEntryPages
(
independentRoot
);
recurIndependentJson
(
independentRoot
,
independentPages
,
sourceRepo
,
(
usingComponents
,
componentKey
)
=>
{
const
componentPath
=
usingComponents
[
componentKey
];
const
newComponentPath
=
getNewComponentPathInIndependentPkg
(
independentRoot
,
componentPath
);
if
(
newComponentPath
&&
newComponentPath
!==
componentPath
)
{
usingComponents
[
componentKey
]
=
`/
${
newComponentPath
}
`
;
}
});
}
copyOuterComponents
(
independentRoot
,
outerComponentSet
,
componentFileCache
)
{
let
copyFiles
=
collectPkgCopyFiles
(
outerComponentSet
,
componentFileCache
);
const
thisCompilationAssets
=
this
.
compilation
.
assets
;
// TODO 组件依赖分许的时候需要记录 绝对路径(js/css/wxml) 进行模块引用的文件,输出后需要更改为相对路径,
copyAllWxComponentsFiles
(
independentRoot
,
copyFiles
,
(
originalFilePath
,
targetPath
,
relativePath
)
=>
{
// 原生组件
if
(
relativePath
.
indexOf
(
wxComponentsStr
)
>=
0
)
{
return
this
.
copyWxComponent
(
independentRoot
,
originalFilePath
,
targetPath
);
}
// vue组件
const
assetInfo
=
thisCompilationAssets
[
relativePath
];
let
assetSource
=
assetInfo
&&
assetInfo
.
source
();
// json文件此时还没有同步到 assets 上
if
(
!
assetSource
&&
relativePath
.
endsWith
(
'
.json
'
))
{
assetSource
=
JSON
.
stringify
(
this
.
emitFileMap
.
get
(
relativePath
));
}
if
(
!
assetSource
)
{
console
.
error
(
'
independent.error
'
,
'
invalid assetSource
'
);
}
const
targetPrefix
=
`
${
independentRoot
}
/
${
outerComponents
}
`
;
const
targetJsAssetName
=
`
${
targetPrefix
}
/
${
relativePath
}
`
;
if
(
relativePath
.
endsWith
(
'
.js
'
))
{
const
originalAsset
=
thisCompilationAssets
[
relativePath
];
const
originalSource
=
originalAsset
&&
originalAsset
.
source
;
// 见 generate-component
const
__$wrappered
=
originalSource
&&
originalSource
.
__$wrappered
;
if
(
__$wrappered
)
{
return
;
}
const
relativeToDist
=
path
.
relative
(
path
.
dirname
(
targetJsAssetName
),
`
${
independentRoot
}
/common/index.js`
);
assetSource
=
`require('
${
relativeToDist
}
');
${
assetSource
}
`
;
}
thisCompilationAssets
[
targetJsAssetName
]
=
generateAsset
(
assetSource
);
});
}
}
module
.
exports
=
Index
;
packages/uni-mp-weixin/lib/independent-plugins/optimize-components-position/copy-wx-components-on-demand/analyze-go-direction.js
0 → 100644
浏览文件 @
65049f2f
const
{
mainPkgName
}
=
require
(
'
../constant
'
);
function
analyzeGoDirection
(
usageMap
,
appJson
,
emitFileMap
)
{
const
copyComponentsForNormalPkgMap
=
{};
const
copyComponentsForMainPkg
=
new
Set
();
const
globalComponents
=
appJson
.
usingComponents
||
{};
for
(
const
[
originalWxComponentPath
,
usageInfo
]
of
usageMap
)
{
const
[
pkgSet
,
pageOrComponentPaths
]
=
usageInfo
;
// 被主包用到 或者 被多个分包用到,则组件放置主包中
if
(
pkgSet
.
has
(
mainPkgName
)
||
pkgSet
.
size
>
1
)
{
copyComponentsForMainPkg
.
add
(
originalWxComponentPath
);
continue
;
}
// 到这里说明仅仅被一个普通分包使用,则将该组件复制到该普通分包中去
const
pkgRoot
=
[...
pkgSet
][
0
];
const
newComponentPath
=
`/
${
pkgRoot
}${
originalWxComponentPath
}
`
;
if
(
!
copyComponentsForNormalPkgMap
[
pkgRoot
])
{
copyComponentsForNormalPkgMap
[
pkgRoot
]
=
new
Set
();
}
copyComponentsForNormalPkgMap
[
pkgRoot
].
add
(
originalWxComponentPath
);
// 当前组件是否是全局组件
const
componentTagInGlobal
=
Object
.
keys
(
globalComponents
).
find
(
compoName
=>
originalWxComponentPath
===
globalComponents
[
compoName
]);
// 该组件 originalWxComponentPath 可能是以全局方式引入有可能是在json文件中声明引用
// 甚至可能是两种方式都存在,只是 tag 不一样
(
pageOrComponentPaths
||
[]).
forEach
(
jsonFilePath
=>
{
const
jsonFileInfo
=
emitFileMap
.
get
(
jsonFilePath
);
// 以全局方式引入该组件
if
(
componentTagInGlobal
)
{
delete
globalComponents
[
componentTagInGlobal
];
// 从全局组件配置中删除
jsonFileInfo
.
usingComponents
[
componentTagInGlobal
]
=
newComponentPath
;
// 更新当前引用路径为分包路径
}
// 以json文件声明方式引入,则需要更新json文件声明的路径
const
usingComponents
=
jsonFileInfo
.
usingComponents
;
const
componentTagInPage
=
Object
.
keys
(
usingComponents
).
find
(
compoName
=>
originalWxComponentPath
===
usingComponents
[
compoName
]);
if
(
componentTagInPage
)
{
jsonFileInfo
.
usingComponents
[
componentTagInPage
]
=
newComponentPath
;
}
if
(
componentTagInPage
||
componentTagInGlobal
)
{
const
replaceInfo
=
`jsonFilePath:
${
jsonFilePath
}
, originalWxComponentPath:
${
originalWxComponentPath
}
, newComponentPath:
${
newComponentPath
}
`
;
// console.log(`replace componentPath used only by normal package, ${replaceInfo}`);
}
});
}
return
{
copyForNormal
:
copyComponentsForNormalPkgMap
,
copyForMain
:
{
[
mainPkgName
]:
copyComponentsForMainPkg
}
};
}
module
.
exports
=
analyzeGoDirection
;
packages/uni-mp-weixin/lib/independent-plugins/optimize-components-position/copy-wx-components-on-demand/collect-wx-component-used-status.js
0 → 100644
浏览文件 @
65049f2f
// 遍历jsonFiles,根据文件路径前缀判断属于哪个包(vue组件完全基于路径划分包归属
const
{
appJsonFileName
,
wxComponentsStr
,
mainPkgName
}
=
require
(
'
../constant
'
);
const
{
getIndependentPkgRoots
,
getNormalPkgRoots
}
=
require
(
'
../util
'
);
// 原生组件被主包和普通分包的使用情况
function
collectWxComponentUsedStatus
(
emitFileMap
)
{
const
normalSubPkgRoots
=
getNormalPkgRoots
();
const
independentSubPkgRoots
=
getIndependentPkgRoots
();
const
usageByPkgMap
=
new
Map
();
for
(
const
[
jsonFileKey
,
jsonFileInfo
]
of
emitFileMap
)
{
if
(
jsonFileKey
===
appJsonFileName
)
{
continue
;
}
const
explicitComponents
=
jsonFileInfo
.
usingComponents
||
{};
// 非全局组件
const
usingGlobalWxComponents
=
jsonFileInfo
.
globalComponentsForOnDemand
||
{};
// FIX 全局组件和直接引用的组件名称相同的情况
const
currentAllComponents
=
Object
.
assign
({},
usingGlobalWxComponents
,
explicitComponents
);
// 忽略独立分包下面的组件或页面,即收集主包和普通分包的依赖情况
const
findPkg
=
subPkgRoot
=>
jsonFileKey
.
startsWith
(
subPkgRoot
);
const
independentPkgRoot
=
independentSubPkgRoots
.
find
(
findPkg
);
// 忽略独立分包页面
if
(
independentPkgRoot
)
continue
;
// 找出当前页面所属包(普通分包页面还是主包页面
const
pkgName
=
normalSubPkgRoots
.
find
(
findPkg
)
||
mainPkgName
;
Object
.
keys
(
currentAllComponents
).
forEach
(
componentName
=>
{
const
componentPath
=
currentAllComponents
[
componentName
];
if
(
componentPath
.
startsWith
(
`/
${
wxComponentsStr
}
`
))
{
if
(
!
usageByPkgMap
.
get
(
componentPath
))
{
usageByPkgMap
.
set
(
componentPath
,
[
new
Set
(),
[]]);
}
usageByPkgMap
.
get
(
componentPath
)[
0
].
add
(
pkgName
);
usageByPkgMap
.
get
(
componentPath
)[
1
].
push
(
jsonFileKey
);
}
});
}
return
usageByPkgMap
;
}
module
.
exports
=
collectWxComponentUsedStatus
;
packages/uni-mp-weixin/lib/independent-plugins/optimize-components-position/copy-wx-components-on-demand/index.js
0 → 100644
浏览文件 @
65049f2f
const
collectWxComponentUsedStatus
=
require
(
'
./collect-wx-component-used-status
'
);
const
processNormalPkg
=
require
(
'
./analyze-go-direction
'
);
const
{
collectPkgCopyFiles
,
copyAllWxComponentsFiles
}
=
require
(
'
../util
'
);
const
{
wxComponentsStr
,
appJsonFileName
,
mainPkgName
}
=
require
(
'
../constant
'
);
const
Analyze
=
require
(
'
../analyze
'
);
// 仅仅针对 [主包]和[普通分包]用到[原生组件]进行按需加载
class
Index
extends
Analyze
{
init
()
{
const
emitFileMap
=
this
.
emitFileMap
;
// 1. 获取app.json
const
appJson
=
emitFileMap
.
get
(
appJsonFileName
);
// 2. 获取每个原生组件(wxComponents)被各分包(主包和普通分包)的引用情况
const
usageByPkgMap
=
collectWxComponentUsedStatus
(
emitFileMap
,
appJson
);
// 3 处理主包和普通分包中的组件引用情况
const
{
copyForNormal
,
copyForMain
,
}
=
processNormalPkg
(
usageByPkgMap
,
appJson
,
emitFileMap
);
// 提示app.json中声明的未被使用的全局原生组件(wxcomponents)
const
rootToWxComponents
=
Object
.
assign
({},
copyForNormal
,
copyForMain
);
const
globalWxComponents
=
appJson
.
usingComponents
||
{};
const
wxComponentPaths
=
[...
copyForMain
.
mainPkg
]
// 主包和普通分包用到的原生组件
Object
.
keys
(
globalWxComponents
).
forEach
(
globalWxComponentKey
=>
{
const
globalWxComponentPath
=
globalWxComponents
[
globalWxComponentKey
];
const
isWxComponents
=
globalWxComponentPath
.
startsWith
(
`/
${
wxComponentsStr
}
`
);
if
(
isWxComponents
&&
!
wxComponentPaths
.
includes
(
globalWxComponentPath
))
{
delete
globalWxComponents
[
globalWxComponentKey
];
// console.log(`global WxComponent(${globalWxComponentKey}) will be removed from global component`);
}
});
// 4. 经过3、4步骤获得每个分包引用的组件情况,对于每个wxcomponent进行依赖分析和提取
const
fileCache
=
{};
this
.
getDependFiles
(
copyForNormal
,
fileCache
);
this
.
getDependFiles
(
copyForMain
,
fileCache
);
// 5.1 文件复制: 普通分包
Object
.
keys
(
copyForNormal
).
forEach
(
pkgRot
=>
{
const
copyFiles
=
collectPkgCopyFiles
(
copyForNormal
[
pkgRot
],
fileCache
,
'
normal pkg
'
);
copyAllWxComponentsFiles
(
pkgRot
,
copyFiles
);
});
// 5.2 文件复制: 主包
const
mainPkgCopyFiles
=
collectPkgCopyFiles
(
copyForMain
[
mainPkgName
],
fileCache
,
'
normal pkg
'
);
copyAllWxComponentsFiles
(
''
,
mainPkgCopyFiles
);
}
}
module
.
exports
=
Index
;
packages/uni-mp-weixin/lib/independent-plugins/optimize-components-position/index.js
0 → 100644
浏览文件 @
65049f2f
const
CopyOuterComponentsForIndependent
=
require
(
'
./copy-outer-components-for-independent
'
);
const
CopyWxComponentOnDemand
=
require
(
'
./copy-wx-components-on-demand
'
);
const
{
getJsonFileMap
}
=
require
(
'
@dcloudio/uni-cli-shared/lib/cache
'
);
const
{
generateAsset
}
=
require
(
'
./util
'
);
const
{
SyncBailHook
}
=
require
(
'
tapable
'
);
// @dcloudio/webpack-uni-mp-loader/lib/plugin/index-new.js
// 需要在在上述插件之后执行(获取处理过的json
class
DependencyAnalyze
{
// wxComponentDependencyAnalyzeHandle 分析微信原生组件的依赖情况
// 后面单独建一个仓库时,指定该类的协议,如需要提供getDepsByComponents方法
constructor
()
{
this
.
AnalyzeWxcomponentDependency
=
require
(
'
../../analyze-wxcomponent-dependency/index
'
)
}
init
(
emitFileMap
,
compilation
)
{
const
thisCompilationAssets
=
compilation
.
assets
;
const
manifestConfig
=
process
.
UNI_MANIFEST
;
const
weixinConfig
=
manifestConfig
[
'
mp-weixin
'
]
||
{};
const
independentSwitch
=
!!
weixinConfig
.
independentSwitch
;
const
copyWxComponentsOnDemandSwitch
=
!!
weixinConfig
.
copyWxComponentsOnDemandSwitch
;
// 默认值false
if
(
copyWxComponentsOnDemandSwitch
)
{
// 开启按需复制
new
CopyWxComponentOnDemand
(
emitFileMap
,
this
.
AnalyzeWxcomponentDependency
,
compilation
).
init
();
}
if
(
independentSwitch
)
{
new
CopyOuterComponentsForIndependent
(
emitFileMap
,
this
.
AnalyzeWxcomponentDependency
,
compilation
).
init
();
}
// TODO 开关控制 按需复制wxcomponents
}
}
module
.
exports
=
DependencyAnalyze
;
packages/uni-mp-weixin/lib/independent-plugins/optimize-components-position/util.js
0 → 100644
浏览文件 @
65049f2f
const
path
=
require
(
'
path
'
);
const
fs
=
require
(
'
fs-extra
'
);
const
{
getGlobalUsingComponents
}
=
require
(
'
@dcloudio/uni-cli-shared/lib/cache
'
);
const
{
wxComponentsStr
,
outerComponents
}
=
require
(
'
./constant
'
);
const
{
generateAsset
}
=
require
(
'
../utils
'
);
function
getGlobalComponentKeyByGlobalComponentPath
()
{
const
globalUsingComponents
=
getGlobalUsingComponents
();
const
globalComponentInfoMap
=
{};
for
(
let
componentKey
in
globalUsingComponents
)
{
const
componentPath
=
globalUsingComponents
[
componentKey
];
globalComponentInfoMap
[
componentPath
]
=
componentKey
;
}
return
globalComponentInfoMap
;
}
function
getIndependentPkgRoots
()
{
return
Object
.
values
(
process
.
UNI_SUBPACKAGES
||
[]).
filter
(
item
=>
item
.
independent
).
map
(
item
=>
item
.
root
);
}
function
getNormalPkgRoots
()
{
return
Object
.
values
(
process
.
UNI_SUBPACKAGES
||
[]).
filter
(
item
=>
!
item
.
independent
).
map
(
item
=>
item
.
root
);
}
function
getIndependentEntryPages
(
subPkgRoot
)
{
const
subPages
=
[];
(
Object
.
keys
(
process
.
UNI_SUB_PACKAGES_ROOT
)
||
[]).
forEach
(
subPkgPagePath
=>
{
const
root
=
process
.
UNI_SUB_PACKAGES_ROOT
[
subPkgPagePath
];
if
(
root
===
subPkgRoot
)
{
subPages
.
push
(
subPkgPagePath
);
}
});
return
subPages
;
}
function
getMainPkgPages
()
{
return
(
process
.
UNI_PAGES
.
pages
||
[]).
map
(
pageInfo
=>
pageInfo
.
path
);
}
function
collectPkgCopyFiles
(
components
,
wxComponentFileDependencyCache
,
logPrefix
=
''
)
{
const
allFiles
=
[];
components
.
forEach
(
component
=>
{
// console.log(logPrefix, `copy component ${component}`);
const
cacheFiles
=
wxComponentFileDependencyCache
[
component
]
||
[];
allFiles
.
push
(...
cacheFiles
);
});
return
allFiles
;
}
function
copyAllWxComponentsFiles
(
key
,
files
=
[],
copyHandler
)
{
const
targetPathPrefix
=
`
${
process
.
env
.
UNI_OUTPUT_DIR
}
/
${
key
}
/`
;
files
.
forEach
(
originalFilePath
=>
{
const
relativePath
=
path
.
relative
(
process
.
env
.
UNI_INPUT_DIR
,
originalFilePath
);
const
targetPath
=
path
.
resolve
(
targetPathPrefix
,
relativePath
);
if
(
copyHandler
)
{
return
copyHandler
(
originalFilePath
,
targetPath
,
relativePath
);
}
fs
.
copySync
(
originalFilePath
,
targetPath
);
});
}
// 不带 首杠
function
getNewComponentPathInIndependentPkg
(
independentRoot
,
componentPath
)
{
// 相对路径不处理
if
(
componentPath
.
startsWith
(
'
.
'
))
{
return
componentPath
;
}
if
(
componentPath
.
startsWith
(
'
/
'
))
{
componentPath
=
componentPath
.
substring
(
1
);
}
if
(
componentPath
.
startsWith
(
`
${
independentRoot
}
`
))
{
return
componentPath
;
}
let
pathPrefix
=
`
${
independentRoot
}
/`
;
if
(
componentPath
.
indexOf
(
wxComponentsStr
)
>=
0
)
{
return
`
${
pathPrefix
}${
componentPath
}
`
;
}
return
`
${
pathPrefix
}${
outerComponents
}
/
${
componentPath
}
`
;
}
// 收集用到的所有包外组件
function
collectAllOutSideComponentsMap
(
independentRoot
,
emitFileMap
,
entryPage
,
cacheForAll
=
new
Set
(),
cacheForGlobal
=
new
Map
())
{
if
(
entryPage
.
startsWith
(
'
/
'
))
{
entryPage
=
entryPage
.
substring
(
1
);
}
const
jsonFileInfo
=
emitFileMap
.
get
(
`
${
entryPage
}
.json`
);
if
(
!
jsonFileInfo
)
{
// 只看vue组件
return
;
}
const
explicitComponents
=
jsonFileInfo
.
usingComponents
||
{};
// 非全局组件
const
usingGlobalComponents
=
jsonFileInfo
.
usingGlobalComponents
||
{};
// 全局组件(忽略原生组件引用全局组件的场景)
const
allUsingComponents
=
Object
.
assign
({},
usingGlobalComponents
,
explicitComponents
);
const
allComponentsPath
=
Object
.
values
(
allUsingComponents
);
const
globalComponents
=
Object
.
values
(
usingGlobalComponents
);
allComponentsPath
.
forEach
(
componentPath
=>
{
if
(
!
componentPath
.
startsWith
(
`/
${
independentRoot
}
`
))
{
cacheForAll
.
add
(
componentPath
);
}
// 全局组件
if
(
globalComponents
.
includes
(
componentPath
))
{
const
originalSet
=
cacheForGlobal
.
get
(
componentPath
);
const
pageSet
=
originalSet
||
new
Set
();
if
(
!
originalSet
)
{
cacheForGlobal
.
set
(
componentPath
,
pageSet
);
}
pageSet
.
add
(
entryPage
);
}
collectAllOutSideComponentsMap
(
independentRoot
,
emitFileMap
,
componentPath
,
cacheForAll
,
cacheForGlobal
);
});
}
function
getJsonByPageOrComponentPath
(
pageOrComponentPath
,
sourceRepo
)
{
const
{
emitFileMap
,
compilationAssets
}
=
sourceRepo
;
if
(
pageOrComponentPath
.
startsWith
(
'
/
'
))
{
pageOrComponentPath
=
pageOrComponentPath
.
substring
(
1
);
}
const
pathWithSuffix
=
`
${
pageOrComponentPath
}
.json`
;
const
assetInfo
=
compilationAssets
[
pathWithSuffix
];
// 原生组件的json文件在copy时保存到了 compilationAssets
const
jsonObj
=
assetInfo
&&
JSON
.
parse
(
assetInfo
.
source
().
toString
());
try
{
return
{
content
:
emitFileMap
.
get
(
pathWithSuffix
)
||
jsonObj
,
fromAssetsFlag
:
!!
jsonObj
};
}
catch
(
e
)
{
console
.
error
(
'
util
'
,
e
);
}
}
function
collectIndependentJsAssets
(
compilationAssets
)
{
const
independentPkgRoots
=
getIndependentPkgRoots
();
const
jsAssets
=
Object
.
keys
(
compilationAssets
).
filter
(
assetName
=>
assetName
.
endsWith
(
'
.js
'
));
return
independentPkgRoots
.
map
(
independentRoot
=>
{
return
{
independentRoot
,
jsAssets
:
jsAssets
.
filter
(
assetName
=>
assetName
.
startsWith
(
independentRoot
))
||
[],
};
});
}
module
.
exports
=
{
getJsonByPageOrComponentPath
,
getNewComponentPathInIndependentPkg
,
collectIndependentJsAssets
,
getGlobalComponentKeyByGlobalComponentPath
,
getNormalPkgRoots
,
getIndependentPkgRoots
,
getIndependentEntryPages
,
getMainPkgPages
,
copyAllWxComponentsFiles
,
collectPkgCopyFiles
,
collectAllOutSideComponentsMap
,
generateAsset
};
packages/uni-mp-weixin/lib/independent-plugins/run-default-app-plugin.js
0 → 100644
浏览文件 @
65049f2f
const
path
=
require
(
'
path
'
);
const
{
generateAsset
}
=
require
(
'
./utils
'
);
// App() 必须在 app.js 中调用,必须调用且只能调用一次。不然会出现无法预期的后果。
class
RunDefaultAppPlugin
{
apply
(
compiler
)
{
compiler
.
hooks
.
emit
.
tapPromise
(
'
RunDefaultAppPlugin
'
,
compilation
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
try
{
// debugger
const
appJsInfo
=
compilation
.
assets
[
"
app.js
"
];
if
(
!
appJsInfo
)
{
console
.
error
(
'
independent.error
'
,
'
invalid runDefaultApp
'
);
resolve
();
return
;
}
const
appSource
=
appJsInfo
.
source
();
// App() 必须在 app.js 中调用,必须调用且只能调用一次。不然会出现无法预期的后果。
const
runApp
=
'
if(getApp && !getApp()){ App({}) }
'
;
compilation
.
assets
[
"
app.js
"
]
=
generateAsset
(
`
${
appSource
}
;
${
runApp
}
`
);
resolve
();
}
catch
(
e
)
{
console
.
error
(
'
independent.error
'
,
'
RunDefaultAppPlugin
'
,
e
);
reject
(
e
);
}
});
});
}
}
module
.
exports
=
RunDefaultAppPlugin
;
\ No newline at end of file
packages/uni-mp-weixin/lib/independent-plugins/split-independent-chunks-plugin.js
0 → 100644
浏览文件 @
65049f2f
const
GraphHelpers
=
require
(
'
webpack/lib/GraphHelpers
'
);
const
{
normalizePath
}
=
require
(
'
@dcloudio/uni-cli-shared
'
);
const
getSplitChunks
=
require
(
'
@dcloudio/vue-cli-plugin-uni/lib/split-chunks
'
);
const
path
=
require
(
'
path
'
);
const
mainPath
=
normalizePath
(
path
.
resolve
(
process
.
env
.
UNI_INPUT_DIR
,
'
main.
'
));
const
mainPkgName
=
'
mainPkg
'
;
function
getAllEntryPointOfChunkGroup
(
chunkGroup
,
entryPointSet
)
{
if
(
chunkGroup
.
isInitial
())
{
return
entryPointSet
.
add
(
chunkGroup
);
}
const
parentChunkGroups
=
[...
chunkGroup
.
parentsIterable
];
parentChunkGroups
.
forEach
(
parentChunkGroup
=>
getAllEntryPointOfChunkGroup
(
parentChunkGroup
,
entryPointSet
));
}
function
getChunkToEntryPointsMap
(
allChunks
)
{
const
chunkToEntryPointsMap
=
new
Map
();
allChunks
.
forEach
(
chunkItem
=>
{
const
chunkGroups
=
[...
chunkItem
.
groupsIterable
];
const
tmpEntryPointSet
=
new
Set
();
chunkToEntryPointsMap
.
set
(
chunkItem
,
tmpEntryPointSet
);
chunkGroups
.
forEach
(
chunkGroup
=>
{
getAllEntryPointOfChunkGroup
(
chunkGroup
,
tmpEntryPointSet
);
});
});
return
chunkToEntryPointsMap
;
}
function
baseTest
(
module
)
{
if
(
module
.
type
===
'
css/mini-extract
'
)
{
return
false
;
}
if
(
module
.
resource
)
{
const
resource
=
normalizePath
(
module
.
resource
);
if
(
resource
.
indexOf
(
'
.vue
'
)
!==
-
1
||
resource
.
indexOf
(
'
.nvue
'
)
!==
-
1
||
resource
.
indexOf
(
mainPath
)
===
0
// main.js
)
{
return
false
;
}
}
return
true
;
}
class
SplitHandler
{
constructor
(
chunks
=
[],
compilation
,
cacheGroups
,
chunkFilter
,
removeModuleFromChunkFilter
=
()
=>
true
)
{
this
.
chunks
=
chunks
||
[];
this
.
chunkFilter
=
chunkFilter
;
this
.
cacheGroups
=
cacheGroups
;
this
.
compilation
=
compilation
;
this
.
removeModuleFromChunkFilter
=
removeModuleFromChunkFilter
;
this
.
chunksInfoMap
=
new
Map
();
}
addModuleToChunksInfoMap
(
module
,
chunks
,
newChunkName
)
{
let
info
=
this
.
chunksInfoMap
.
get
(
newChunkName
);
if
(
!
info
)
{
info
=
{
modules
:
new
Set
(),
chunks
:
new
Set
(),
};
this
.
chunksInfoMap
.
set
(
newChunkName
,
info
);
}
info
.
modules
.
add
(
module
);
chunks
.
forEach
(
chunk
=>
info
.
chunks
.
add
(
chunk
));
}
checkTest
(
module
,
test
)
{
if
(
typeof
test
===
'
function
'
)
{
if
(
test
(
module
,
module
.
getChunks
()))
{
return
true
;
}
}
else
if
(
test
instanceof
RegExp
)
{
if
(
module
.
nameForCondition
&&
test
.
test
(
module
.
nameForCondition
()))
{
return
true
;
}
for
(
const
chunk
of
module
.
getChunks
())
{
if
(
chunk
.
name
&&
test
.
test
(
chunk
.
name
))
{
return
true
;
}
}
}
return
false
;
}
getHitCacheGroups
(
module
)
{
const
hitCacheGroups
=
[];
const
cacheGroups
=
this
.
cacheGroups
;
for
(
const
key
of
Object
.
keys
(
cacheGroups
))
{
const
cacheInfo
=
cacheGroups
[
key
];
if
(
!
cacheInfo
)
{
continue
;
}
if
(
this
.
checkTest
(
module
,
cacheInfo
.
test
))
{
hitCacheGroups
.
push
({
newChunkName
:
cacheInfo
.
name
,
priority
:
cacheInfo
.
priority
||
0
});
}
}
if
(
hitCacheGroups
.
length
)
{
return
hitCacheGroups
.
sort
((
b
,
a
)
=>
a
.
priority
-
b
.
priority
)[
0
];
}
return
null
;
}
start
()
{
const
allModulesSet
=
new
Set
();
this
.
chunks
.
forEach
(
chunk
=>
{
chunk
.
getModules
().
forEach
(
module
=>
allModulesSet
.
add
(
module
));
});
this
.
splitHandler
([...
allModulesSet
]);
}
filter
(
module
)
{
// 获取chunks和this.chunks的交集部分
const
filterOne
=
this
.
chunks
.
filter
(
targetChunk
=>
module
.
chunksIterable
.
has
(
targetChunk
))
||
[];
// 处理uniapp提供的过滤,见split-chunks文件
return
filterOne
.
filter
(
this
.
chunkFilter
);
}
splitHandler
(
allModulesUsedByIndependent
)
{
// 遍历独立分包中用到的模块,测试其所在的cacheGroup
// 每个模块在这里至多会生成或加入到一个newChunk中
for
(
const
module
of
allModulesUsedByIndependent
)
{
const
hitGroup
=
this
.
getHitCacheGroups
(
module
);
if
(
!
hitGroup
)
{
continue
;
}
this
.
addModuleToChunksInfoMap
(
module
,
this
.
filter
(
module
),
hitGroup
.
newChunkName
);
}
// 遍历 chunksInfoMap
for
(
const
[
chunkName
,
newChunkInfo
]
of
this
.
chunksInfoMap
)
{
const
newChunk
=
this
.
compilation
.
addChunk
(
chunkName
);
newChunk
.
chunkReason
=
'
split chunk for independent
'
;
for
(
const
module
of
newChunkInfo
.
modules
)
{
if
(
module
.
rawRequest
&&
module
.
rawRequest
.
indexOf
(
'
wx-recorder-manager
'
)
>=
0
)
{
// console.log('sunqing');
}
GraphHelpers
.
connectChunkAndModule
(
newChunk
,
module
);
[...
newChunkInfo
.
chunks
].
forEach
(
chunk
=>
{
if
(
this
.
removeModuleFromChunkFilter
(
chunk
))
{
chunk
.
removeModule
(
module
);
chunk
.
split
(
newChunk
);
}
});
}
}
}
}
class
SplitIndependentChunksPlugin
{
generateCacheGroups
()
{
const
cacheGroups
=
{};
Object
.
keys
(
process
.
UNI_SUBPACKAGES
).
forEach
(
root
=>
{
const
pkgInfo
=
process
.
UNI_SUBPACKAGES
[
root
];
if
(
pkgInfo
.
independent
)
{
cacheGroups
[
root
]
=
{
[
root
+
'
/commonsVendor
'
]:
{
test
:
/
[\\/]
node_modules
[\\/]
/
,
minSize
:
0
,
minChunks
:
1
,
name
:
normalizePath
(
path
.
join
(
root
,
'
common/library
'
)),
priority
:
2
,
chunks
:
'
all
'
,
},
[
root
+
'
/commons
'
]:
{
priority
:
1
,
name
:
normalizePath
(
path
.
join
(
root
,
'
common/vendor
'
)),
test
:
(
module
)
=>
{
if
(
!
baseTest
(
module
))
{
return
false
;
}
return
true
;
},
},
};
}
});
const
splitChunkConfig
=
getSplitChunks
();
cacheGroups
[
mainPkgName
]
=
splitChunkConfig
.
cacheGroups
;
return
{
cacheGroups
,
chunkFilter
:
splitChunkConfig
.
chunks
};
}
apply
(
compiler
)
{
compiler
.
hooks
.
thisCompilation
.
tap
(
'
SplitIndependentChunksPlugin
'
,
compilation
=>
{
compilation
.
hooks
.
optimizeChunksAdvanced
.
tap
(
'
SplitIndependentChunksPlugin
'
,
chunks
=>
{
try
{
const
independentPkgRoot
=
Object
.
values
(
process
.
UNI_SUBPACKAGES
).
filter
(
rootInfo
=>
rootInfo
.
independent
).
map
(
rootInfo
=>
rootInfo
.
root
);
const
allPkgRootMap
=
{};
const
mainPkgChunks
=
[];
for
(
const
chunk
of
chunks
)
{
const
chunkName
=
chunk
.
name
;
if
(
!
chunkName
)
{
continue
;
}
const
root
=
independentPkgRoot
.
find
(
root
=>
chunkName
.
startsWith
(
root
));
if
(
!
root
)
{
mainPkgChunks
.
push
(
chunk
);
continue
;
}
if
(
!
allPkgRootMap
[
root
])
{
allPkgRootMap
[
root
]
=
[];
}
allPkgRootMap
[
root
].
push
(
chunk
);
}
const
{
cacheGroups
,
chunkFilter
}
=
this
.
generateCacheGroups
(
compiler
);
// 找出chunk所有的entryPoint
const
chunkToEntryPointsMap
=
getChunkToEntryPointsMap
(
compilation
.
chunks
);
const
allChunksUsedByIndependentMap
=
{};
for
(
const
pkgRoot
in
allPkgRootMap
)
{
if
(
!
allChunksUsedByIndependentMap
[
pkgRoot
])
{
allChunksUsedByIndependentMap
[
pkgRoot
]
=
new
Set
();
}
for
(
const
[
chunkItem
,
entryPointSet
]
of
chunkToEntryPointsMap
)
{
const
filter
=
entryPoint
=>
entryPoint
.
name
.
startsWith
(
pkgRoot
);
const
referenceByPkgRoot
=
[...
entryPointSet
].
find
(
filter
);
// 当前chunk中存在模块被该独立分包下面的页面引用
// uniapp的entry: main.js + page.vue
if
(
referenceByPkgRoot
)
{
allChunksUsedByIndependentMap
[
pkgRoot
].
add
(
chunkItem
);
}
}
}
// 先分离独立分包
for
(
const
pkgRoot
in
allPkgRootMap
)
{
const
chunksOfIndependentPkg
=
allPkgRootMap
[
pkgRoot
];
// 需要将独立分包中用到外部js模块拆分一份到 pkgRoot/vendor.js 中
const
allChunksUsedByIndependent
=
[...
allChunksUsedByIndependentMap
[
pkgRoot
]];
// 收集独立分包下面的所有chunks:包内chunks + 包外chunks(主要引用的包外组件)
const
outSideChunks
=
[];
allChunksUsedByIndependent
.
forEach
(
chunkItem
=>
{
if
(
!
chunksOfIndependentPkg
.
includes
(
chunkItem
))
{
outSideChunks
.
push
(
chunkItem
);
}
});
new
SplitHandler
([...
allChunksUsedByIndependent
],
compilation
,
cacheGroups
[
pkgRoot
],
chunkFilter
,
(
chunk
)
=>
{
if
(
outSideChunks
.
includes
(
chunk
))
{
return
false
;
}
return
true
;
}).
start
();
}
// 再分离普通分包和主包
new
SplitHandler
(
mainPkgChunks
,
compilation
,
cacheGroups
[
mainPkgName
],
chunkFilter
).
start
();
}
catch
(
e
)
{
console
.
error
(
'
independent.error
'
,
'
SplitIndependentChunksPlugin
'
,
e
);
}
});
});
}
}
module
.
exports
=
SplitIndependentChunksPlugin
;
packages/uni-mp-weixin/lib/independent-plugins/utils.js
0 → 100644
浏览文件 @
65049f2f
const
isWin
=
/^win/
.
test
(
process
.
platform
);
const
normalizePath
=
path
=>
(
isWin
?
path
.
replace
(
/
\\
/g
,
'
/
'
)
:
path
);
module
.
exports
=
{
normalizePath
,
generateAsset
(
stringSource
)
{
return
{
size
()
{
return
Buffer
.
byteLength
(
stringSource
,
'
utf8
'
);
},
source
()
{
return
stringSource
;
},
};
},
};
packages/uni-mp-weixin/lib/runtime/index.js
0 → 100644
浏览文件 @
65049f2f
const
path
=
require
(
'
path
'
);
module
.
exports
=
function
()
{
return
path
.
resolve
(
__dirname
)
+
'
/wxMpRuntime.js
'
;
};
\ No newline at end of file
packages/uni-mp-weixin/lib/runtime/wxMpRuntime.js
0 → 100644
浏览文件 @
65049f2f
if
(
!
global
.
wpRuntimeInited
)
{
global
.
wpRuntimeInited
=
true
;
// https://developers.weixin.qq.com/miniprogram/dev/reference/api/App.html
// 注册小程序。接受一个 Object 参数,其指定小程序的生命周期回调等。
// App() 必须在 app.js 中调用,必须调用且只能调用一次。不然会出现无法预期的后果。
const
independentRoots
=
[];
// 变量名不能更改,插件通过该名来静态替换值
Object
.
assign
(
global
,
{
getApp
:
function
()
{
return
getApp
()
||
getApp
({
allowDefault
:
true
});
},
App
:
function
(
appOpts
=
{})
{
const
launchOptions
=
wx
.
getLaunchOptionsSync
();
const
entryPath
=
launchOptions
.
path
||
''
;
const
isIndependentPage
=
independentRoots
.
find
(
pkgRoot
=>
entryPath
.
startsWith
(
pkgRoot
));
// 实际上也可以不区分
if
(
!
isIndependentPage
)
{
return
App
(
appOpts
);
}
// TODO 部分App上面挂载的东西 未提供api形式,这里可能不支持
// 目前只针对云医用到的生命周期进行支持
const
app
=
this
.
getApp
();
// const { onLaunch, onShow, onHide, onError, onUnhandledRejection, onThemeChange } = appOpts;
Object
.
assign
(
app
,
appOpts
);
app
.
onLaunch
(
launchOptions
);
wx
.
onAppShow
(
opts
=>
app
.
onShow
(
opts
));
wx
.
onAppHide
(
opts
=>
app
.
onHide
(
opts
));
wx
.
onError
(
opts
=>
app
.
onError
(
opts
));
wx
.
onUnhandledRejection
(
opts
=>
app
.
onUnhandledRejection
(
opts
));
wx
.
onThemeChange
(
opts
=>
app
.
onThemeChange
(
opts
));
},
});
}
packages/uni-mp-weixin/lib/uni.config.js
浏览文件 @
65049f2f
...
@@ -42,13 +42,19 @@ module.exports = {
...
@@ -42,13 +42,19 @@ module.exports = {
const
workers
=
platformOptions
.
workers
const
workers
=
platformOptions
.
workers
workers
&&
copyOptions
.
push
(
workers
)
workers
&&
copyOptions
.
push
(
workers
)
const
wxcomponentsDir
=
path
.
resolve
(
process
.
env
.
UNI_INPUT_DIR
,
COMPONENTS_DIR_NAME
)
const
manifestConfig
=
process
.
UNI_MANIFEST
;
if
(
fs
.
existsSync
(
wxcomponentsDir
))
{
const
weixinConfig
=
manifestConfig
[
'
mp-weixin
'
]
||
{};
copyOptions
.
push
({
const
copyWxComponentsOnDemandSwitch
=
!!
weixinConfig
.
copyWxComponentsOnDemandSwitch
;
// 默认值false
from
:
wxcomponentsDir
,
to
:
COMPONENTS_DIR_NAME
,
if
(
!
copyWxComponentsOnDemandSwitch
)
{
ignore
:
[
'
**/*.vue
'
,
'
**/*.css
'
]
// v3 会自动转换生成vue,css文件,需要过滤
const
wxcomponentsDir
=
path
.
resolve
(
process
.
env
.
UNI_INPUT_DIR
,
COMPONENTS_DIR_NAME
);
})
if
(
fs
.
existsSync
(
wxcomponentsDir
))
{
copyOptions
.
push
({
from
:
wxcomponentsDir
,
to
:
COMPONENTS_DIR_NAME
,
ignore
:
[
'
**/*.vue
'
,
'
**/*.css
'
]
// v3 会自动转换生成vue,css文件,需要过滤
});
}
}
}
global
.
uniModules
.
forEach
(
module
=>
{
global
.
uniModules
.
forEach
(
module
=>
{
const
wxcomponentsDir
=
path
.
resolve
(
process
.
env
.
UNI_INPUT_DIR
,
'
uni_modules
'
,
module
,
COMPONENTS_DIR_NAME
)
const
wxcomponentsDir
=
path
.
resolve
(
process
.
env
.
UNI_INPUT_DIR
,
'
uni_modules
'
,
module
,
COMPONENTS_DIR_NAME
)
...
...
packages/vue-cli-plugin-uni/lib/mp/index.js
浏览文件 @
65049f2f
...
@@ -23,6 +23,8 @@ function createUniMPPlugin () {
...
@@ -23,6 +23,8 @@ function createUniMPPlugin () {
return
new
WebpackUniMPPlugin
()
return
new
WebpackUniMPPlugin
()
}
}
const
createWxMpIndependentPlugins
=
require
(
'
@dcloudio/uni-mp-weixin/lib/createIndependentPlugin
'
);
function
getProvides
()
{
function
getProvides
()
{
const
uniPath
=
require
(
'
@dcloudio/uni-cli-shared/lib/platform
'
).
getMPRuntimePath
()
const
uniPath
=
require
(
'
@dcloudio/uni-cli-shared/lib/platform
'
).
getMPRuntimePath
()
const
uniCloudPath
=
path
.
resolve
(
__dirname
,
'
../../packages/uni-cloud/dist/index.js
'
)
const
uniCloudPath
=
path
.
resolve
(
__dirname
,
'
../../packages/uni-cloud/dist/index.js
'
)
...
@@ -170,7 +172,8 @@ module.exports = {
...
@@ -170,7 +172,8 @@ module.exports = {
const
plugins
=
[
const
plugins
=
[
new
WebpackUniAppPlugin
(),
new
WebpackUniAppPlugin
(),
createUniMPPlugin
(),
createUniMPPlugin
(),
new
webpack
.
ProvidePlugin
(
getProvides
())
new
webpack
.
ProvidePlugin
(
getProvides
()),
...
createWxMpIndependentPlugins
()
]
]
if
((
process
.
env
.
UNI_SUBPACKGE
||
process
.
env
.
UNI_MP_PLUGIN
)
&&
process
.
env
.
UNI_SUBPACKGE
!==
'
main
'
)
{
if
((
process
.
env
.
UNI_SUBPACKGE
||
process
.
env
.
UNI_MP_PLUGIN
)
&&
process
.
env
.
UNI_SUBPACKGE
!==
'
main
'
)
{
...
...
packages/vue-cli-plugin-uni/lib/split-chunks.js
浏览文件 @
65049f2f
...
@@ -4,6 +4,13 @@ const {
...
@@ -4,6 +4,13 @@ const {
normalizePath
normalizePath
}
=
require
(
'
@dcloudio/uni-cli-shared
'
)
}
=
require
(
'
@dcloudio/uni-cli-shared
'
)
const
subPkgsInfo
=
Object
.
values
(
process
.
UNI_SUBPACKAGES
);
const
normalFilter
=
({
independent
})
=>
!
independent
;
const
independentFilter
=
({
independent
})
=>
independent
;
const
map2Root
=
({
root
})
=>
root
+
'
/
'
;
const
normalSubPackageRoots
=
subPkgsInfo
.
filter
(
normalFilter
).
map
(
map2Root
);
const
independentSubpackageRoots
=
subPkgsInfo
.
filter
(
independentFilter
).
map
(
map2Root
);
function
createCacheGroups
()
{
function
createCacheGroups
()
{
const
cacheGroups
=
{}
const
cacheGroups
=
{}
if
(
process
.
UNI_CONFUSION
)
{
// 加密
if
(
process
.
UNI_CONFUSION
)
{
// 加密
...
@@ -152,7 +159,7 @@ module.exports = function getSplitChunks () {
...
@@ -152,7 +159,7 @@ module.exports = function getSplitChunks () {
const
findSubPackages
=
function
(
chunks
)
{
const
findSubPackages
=
function
(
chunks
)
{
return
chunks
.
reduce
((
pkgs
,
item
)
=>
{
return
chunks
.
reduce
((
pkgs
,
item
)
=>
{
const
name
=
normalizePath
(
item
.
name
)
const
name
=
normalizePath
(
item
.
name
)
const
pkgRoot
=
s
ubPackageRoots
.
find
(
root
=>
name
.
indexOf
(
root
)
===
0
)
const
pkgRoot
=
normalS
ubPackageRoots
.
find
(
root
=>
name
.
indexOf
(
root
)
===
0
)
pkgRoot
&&
pkgs
.
add
(
pkgRoot
)
pkgRoot
&&
pkgs
.
add
(
pkgRoot
)
return
pkgs
return
pkgs
},
new
Set
())
},
new
Set
())
...
@@ -178,7 +185,12 @@ module.exports = function getSplitChunks () {
...
@@ -178,7 +185,12 @@ module.exports = function getSplitChunks () {
console
.
log
(
'
move module to main chunk:
'
,
module
.
resource
,
console
.
log
(
'
move module to main chunk:
'
,
module
.
resource
,
'
from
'
,
subPackageRoot
,
'
for component in main package:
'
,
resource
)
'
from
'
,
subPackageRoot
,
'
for component in main package:
'
,
resource
)
}
}
return
true
// 独立分包除外
const
independentRoot
=
independentSubpackageRoots
.
find
(
root
=>
resource
.
indexOf
(
root
)
>=
0
);
if
(
!
independentRoot
)
{
return
true
;
}
}
}
}
else
{
}
else
{
return
hasMainPackageComponent
(
m
.
module
,
subPackageRoot
)
return
hasMainPackageComponent
(
m
.
module
,
subPackageRoot
)
...
...
packages/webpack-uni-mp-loader/lib/plugin/generate-component.js
浏览文件 @
65049f2f
...
@@ -62,6 +62,7 @@ let lastComponents = []
...
@@ -62,6 +62,7 @@ let lastComponents = []
// TODO 解决方案不太理想
// TODO 解决方案不太理想
module
.
exports
=
function
generateComponent
(
compilation
,
jsonpFunction
=
'
webpackJsonp
'
)
{
module
.
exports
=
function
generateComponent
(
compilation
,
jsonpFunction
=
'
webpackJsonp
'
)
{
const
curComponents
=
[]
const
curComponents
=
[]
const
componentChunkNameMap
=
{}
const
components
=
getComponentSet
()
const
components
=
getComponentSet
()
if
(
components
.
size
)
{
if
(
components
.
size
)
{
const
assets
=
compilation
.
assets
const
assets
=
compilation
.
assets
...
@@ -71,9 +72,14 @@ module.exports = function generateComponent (compilation, jsonpFunction = 'webpa
...
@@ -71,9 +72,14 @@ module.exports = function generateComponent (compilation, jsonpFunction = 'webpa
const
uniModuleId
=
modules
.
find
(
module
=>
module
.
resource
&&
normalizePath
(
module
.
resource
)
===
uniPath
).
id
const
uniModuleId
=
modules
.
find
(
module
=>
module
.
resource
&&
normalizePath
(
module
.
resource
)
===
uniPath
).
id
const
styleImports
=
{}
const
styleImports
=
{}
const
fixSlots
=
{}
const
fixSlots
=
{}
const
vueOuterComponentSting
=
'
vueOuterComponents
'
Object
.
keys
(
assets
).
forEach
(
name
=>
{
Object
.
keys
(
assets
).
forEach
(
name
=>
{
if
(
components
.
has
(
name
.
replace
(
'
.js
'
,
''
)))
{
// 判断是不是vue
const
isVueComponent
=
components
.
has
(
name
.
replace
(
'
.js
'
,
''
))
// 独立分包外面的组件,复制到独立分包内,在components中看不到,所以需要单独处理
const
isVueOuterComponent
=
Boolean
(
name
.
endsWith
(
'
.js
'
)
&&
name
.
indexOf
(
vueOuterComponentSting
)
>=
0
)
if
(
isVueComponent
||
isVueOuterComponent
)
{
curComponents
.
push
(
name
.
replace
(
'
.js
'
,
''
))
curComponents
.
push
(
name
.
replace
(
'
.js
'
,
''
))
if
(
assets
[
name
].
source
.
__$wrappered
)
{
if
(
assets
[
name
].
source
.
__$wrappered
)
{
...
@@ -99,6 +105,15 @@ module.exports = function generateComponent (compilation, jsonpFunction = 'webpa
...
@@ -99,6 +105,15 @@ module.exports = function generateComponent (compilation, jsonpFunction = 'webpa
}
}
const
origSource
=
assets
[
name
].
source
()
const
origSource
=
assets
[
name
].
source
()
if
(
isVueComponent
)
{
componentChunkNameMap
[
name
]
=
moduleId
}
else
if
(
isVueOuterComponent
)
{
const
startIndex
=
name
.
indexOf
(
vueOuterComponentSting
)
+
vueOuterComponentSting
.
length
+
1
;
const
rightOriginalComponentName
=
name
.
substring
(
startIndex
)
moduleId
=
componentChunkNameMap
[
rightOriginalComponentName
]
}
if
(
origSource
.
length
!==
EMPTY_COMPONENT_LEN
)
{
// 不是空组件
if
(
origSource
.
length
!==
EMPTY_COMPONENT_LEN
)
{
// 不是空组件
const
globalVar
=
process
.
env
.
UNI_PLATFORM
===
'
mp-alipay
'
?
'
my
'
:
'
global
'
const
globalVar
=
process
.
env
.
UNI_PLATFORM
===
'
mp-alipay
'
?
'
my
'
:
'
global
'
// 主要是为了解决支付宝旧版本, Component 方法只在组件 js 里有,需要挂在 my.defineComponent
// 主要是为了解决支付宝旧版本, Component 方法只在组件 js 里有,需要挂在 my.defineComponent
...
@@ -300,7 +315,7 @@ function addComponent (name) {
...
@@ -300,7 +315,7 @@ function addComponent (name) {
function
removeUnusedComponent
(
name
)
{
function
removeUnusedComponent
(
name
)
{
try
{
try
{
fs
.
renameSync
(
path
.
join
(
process
.
env
.
UNI_OUTPUT_DIR
,
name
+
'
.json
'
),
path
.
join
(
process
.
env
.
UNI_OUTPUT_DIR
,
name
+
//
fs.renameSync(path.join(process.env.UNI_OUTPUT_DIR, name + '.json'), path.join(process.env.UNI_OUTPUT_DIR, name +
'
.bak.json
'
))
//
'.bak.json'))
}
catch
(
e
)
{
}
}
catch
(
e
)
{
}
}
}
packages/webpack-uni-mp-loader/lib/plugin/generate-json.js
浏览文件 @
65049f2f
...
@@ -7,7 +7,8 @@ const {
...
@@ -7,7 +7,8 @@ const {
const
{
const
{
getPageSet
,
getPageSet
,
getJsonFileMap
,
getJsonFileMap
,
getChangedJsonFileMap
getChangedJsonFileMap
,
supportGlobalUsingComponents
}
=
require
(
'
@dcloudio/uni-cli-shared/lib/cache
'
)
}
=
require
(
'
@dcloudio/uni-cli-shared/lib/cache
'
)
// 主要解决 extends 且未实际引用的组件
// 主要解决 extends 且未实际引用的组件
...
@@ -25,6 +26,8 @@ const mpBaiduDynamicLibs = [
...
@@ -25,6 +26,8 @@ const mpBaiduDynamicLibs = [
'
dynamicLib://myDynamicLib/vrvideo
'
'
dynamicLib://myDynamicLib/vrvideo
'
]
]
const
AnalyzeDependency
=
require
(
'
@dcloudio/uni-mp-weixin/lib/independent-plugins/optimize-components-position/index
'
);
function
analyzeUsingComponents
()
{
function
analyzeUsingComponents
()
{
if
(
!
process
.
env
.
UNI_OPT_SUBPACKAGES
)
{
if
(
!
process
.
env
.
UNI_OPT_SUBPACKAGES
)
{
return
return
...
@@ -109,6 +112,7 @@ function normalizeUsingComponents (file, usingComponents) {
...
@@ -109,6 +112,7 @@ function normalizeUsingComponents (file, usingComponents) {
return
usingComponents
return
usingComponents
}
}
const
emitFileMap
=
new
Map
();
module
.
exports
=
function
generateJson
(
compilation
)
{
module
.
exports
=
function
generateJson
(
compilation
)
{
analyzeUsingComponents
()
analyzeUsingComponents
()
...
@@ -124,10 +128,9 @@ module.exports = function generateJson (compilation) {
...
@@ -124,10 +128,9 @@ module.exports = function generateJson (compilation) {
}
}
delete
jsonObj
.
customUsingComponents
delete
jsonObj
.
customUsingComponents
// usingGlobalComponents
// usingGlobalComponents
if
(
jsonObj
.
usingGlobalComponents
&&
Object
.
keys
(
jsonObj
.
usingGlobalComponents
).
length
)
{
if
(
!
supportGlobalUsingComponents
&&
jsonObj
.
usingGlobalComponents
&&
Object
.
keys
(
jsonObj
.
usingGlobalComponents
).
length
)
{
jsonObj
.
usingComponents
=
Object
.
assign
(
jsonObj
.
usingGlobalComponents
,
jsonObj
.
usingComponents
)
jsonObj
.
usingComponents
=
Object
.
assign
(
jsonObj
.
usingGlobalComponents
,
jsonObj
.
usingComponents
)
}
}
delete
jsonObj
.
usingGlobalComponents
// usingAutoImportComponents
// usingAutoImportComponents
if
(
jsonObj
.
usingAutoImportComponents
&&
Object
.
keys
(
jsonObj
.
usingAutoImportComponents
).
length
)
{
if
(
jsonObj
.
usingAutoImportComponents
&&
Object
.
keys
(
jsonObj
.
usingAutoImportComponents
).
length
)
{
...
@@ -209,7 +212,31 @@ module.exports = function generateJson (compilation) {
...
@@ -209,7 +212,31 @@ module.exports = function generateJson (compilation) {
if
((
process
.
env
.
UNI_SUBPACKGE
||
process
.
env
.
UNI_MP_PLUGIN
)
&&
jsonObj
.
usingComponents
)
{
if
((
process
.
env
.
UNI_SUBPACKGE
||
process
.
env
.
UNI_MP_PLUGIN
)
&&
jsonObj
.
usingComponents
)
{
jsonObj
.
usingComponents
=
normalizeUsingComponents
(
name
,
jsonObj
.
usingComponents
)
jsonObj
.
usingComponents
=
normalizeUsingComponents
(
name
,
jsonObj
.
usingComponents
)
}
}
const
source
=
JSON
.
stringify
(
jsonObj
,
null
,
2
)
emitFileMap
.
set
(
name
,
jsonObj
);
}
// 组件依赖分析
(
new
AnalyzeDependency
()).
init
(
emitFileMap
,
compilation
);
for
(
const
[
name
,
jsonObj
]
of
emitFileMap
)
{
emit
(
name
,
jsonObj
,
compilation
);
delete
jsonObj
.
usingGlobalComponents
;
}
if
(
process
.
env
.
UNI_USING_CACHE
&&
jsonFileMap
.
size
)
{
setTimeout
(()
=>
{
require
(
'
@dcloudio/uni-cli-shared/lib/cache
'
).
store
()
},
50
)
}
}
function
emit
(
name
,
jsonObj
,
compilation
)
{
if
(
jsonObj
.
usingComponents
)
{
jsonObj
.
usingComponents
=
Object
.
assign
({},
jsonObj
.
usingComponents
);
}
const
source
=
JSON
.
stringify
(
jsonObj
,
null
,
2
)
const
jsFile
=
name
.
replace
(
'
.json
'
,
'
.js
'
)
const
jsFile
=
name
.
replace
(
'
.json
'
,
'
.js
'
)
if
(
if
(
...
@@ -243,11 +270,6 @@ module.exports = function generateJson (compilation) {
...
@@ -243,11 +270,6 @@ module.exports = function generateJson (compilation) {
}
}
}
}
compilation
.
assets
[
name
]
=
jsonAsset
compilation
.
assets
[
name
]
=
jsonAsset
}
if
(
process
.
env
.
UNI_USING_CACHE
&&
jsonFileMap
.
size
)
{
setTimeout
(()
=>
{
require
(
'
@dcloudio/uni-cli-shared/lib/cache
'
).
store
()
},
50
)
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录