Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
小浣熊撸代码
uni-app
提交
ae22205f
U
uni-app
项目概览
小浣熊撸代码
/
uni-app
与 Fork 源项目一致
Fork自
DCloud / uni-app
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
uni-app
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
ae22205f
编写于
1月 28, 2021
作者:
fxy060608
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(cli): add inject
上级
3aaeecc9
变更
5
显示空白变更内容
内联
并排
Showing
5 changed file
with
304 addition
and
4 deletion
+304
-4
packages/vite-plugin-uni/src/configResolved/plugins/index.ts
packages/vite-plugin-uni/src/configResolved/plugins/index.ts
+26
-1
packages/vite-plugin-uni/src/configResolved/plugins/inject.ts
...ages/vite-plugin-uni/src/configResolved/plugins/inject.ts
+273
-0
packages/vite-plugin-uni/src/configResolved/plugins/pre.ts
packages/vite-plugin-uni/src/configResolved/plugins/pre.ts
+3
-1
packages/vite-plugin-uni/src/configResolved/plugins/preCss.ts
...ages/vite-plugin-uni/src/configResolved/plugins/preCss.ts
+1
-1
packages/vite-plugin-uni/src/resolveId.ts
packages/vite-plugin-uni/src/resolveId.ts
+1
-1
未找到文件。
packages/vite-plugin-uni/src/configResolved/plugins/index.ts
浏览文件 @
ae22205f
...
...
@@ -6,6 +6,7 @@ import { uniPrePlugin } from './pre'
import
{
uniJsonPlugin
}
from
'
./json
'
import
{
uniPreCssPlugin
}
from
'
./preCss
'
import
{
uniEasycomPlugin
}
from
'
./easycom
'
import
{
InjectOptions
,
uniInjectPlugin
}
from
'
./inject
'
const
debugPlugin
=
debug
(
'
uni:plugin
'
)
export
interface
UniPluginFilterOptions
extends
VitePluginUniResolvedOptions
{
...
...
@@ -24,6 +25,9 @@ const uniPrePluginOptions: Partial<UniPluginFilterOptions> = {
/
\/
vue-router
\/
/
,
/
\/
vuex
\/
/
,
/@dcloudio
\/
uni-shared/
,
/vite
\/
preload-helper/
,
/vite
\/
dynamic-import-polyfill/
,
/
\.
html$/
,
UNI_H5_RE
,
],
}
...
...
@@ -32,7 +36,21 @@ const uniPreCssPluginOptions: Partial<UniPluginFilterOptions> = {
}
const
uniEasycomPluginOptions
:
Partial
<
UniPluginFilterOptions
>
=
{
exclude
:
[
UNI_H5_RE
],
exclude
:
[
/App.vue$/
,
UNI_H5_RE
],
}
const
uniInjectPluginOptions
:
Partial
<
InjectOptions
>
=
{
exclude
:
[
/@dcloudio
\/
uni-h5-vue/
,
/@dcloudio
\/
uni-shared/
,
/
\/
vue-router
\/
/
,
/@vue
\/
shared/
,
],
'
__GLOBAL__.
'
:
'
@dcloudio/uni-h5
'
,
'
uni.
'
:
'
@dcloudio/uni-h5
'
,
getApp
:
[
'
@dcloudio/uni-h5
'
,
'
getApp
'
],
getCurrentPages
:
[
'
@dcloudio/uni-h5
'
,
'
getCurrentPages
'
],
UniServiceJSBridge
:
[
'
@dcloudio/uni-h5
'
,
'
UniServiceJSBridge
'
],
}
export
function
resolvePlugins
(
...
...
@@ -51,6 +69,13 @@ export function resolvePlugins(
uniPreCssPlugin
(
Object
.
assign
(
uniPreCssPluginOptions
,
options
)),
'
vite:css
'
)
if
(
!
options
.
devServer
)
{
addPlugin
(
plugins
,
uniInjectPlugin
(
Object
.
assign
(
uniInjectPluginOptions
,
options
)),
'
vite:vue
'
)
}
addPlugin
(
plugins
,
uniEasycomPlugin
(
Object
.
assign
(
uniEasycomPluginOptions
,
options
)),
...
...
packages/vite-plugin-uni/src/configResolved/plugins/inject.ts
0 → 100644
浏览文件 @
ae22205f
import
path
,
{
sep
}
from
'
path
'
import
debug
from
'
debug
'
import
{
Plugin
,
ViteDevServer
}
from
'
vite
'
import
{
BaseNode
,
Program
,
Property
,
Identifier
,
MemberExpression
,
MethodDefinition
,
ExportSpecifier
,
}
from
'
estree
'
import
{
attachScopes
,
createFilter
,
makeLegalIdentifier
,
}
from
'
@rollup/pluginutils
'
import
{
AcornNode
}
from
'
rollup
'
import
{
walk
}
from
'
estree-walker
'
import
MagicString
from
'
magic-string
'
import
{
UniPluginFilterOptions
}
from
'
.
'
interface
Scope
{
parent
:
Scope
contains
:
(
name
:
string
)
=>
boolean
}
type
Injectment
=
string
|
[
string
,
string
]
export
interface
InjectOptions
extends
UniPluginFilterOptions
{
sourceMap
?:
boolean
[
str
:
string
]:
Injectment
|
InjectOptions
[
'
include
'
]
|
Boolean
|
ViteDevServer
}
const
debugInject
=
debug
(
'
uni:inject
'
)
const
debugInjectTry
=
debug
(
'
uni:inject-try
'
)
export
function
uniInjectPlugin
(
options
:
InjectOptions
):
Plugin
{
if
(
!
options
)
throw
new
Error
(
'
Missing options
'
)
const
filter
=
createFilter
(
options
.
include
,
options
.
exclude
)
const
modules
=
Object
.
assign
({},
options
)
as
{
[
str
:
string
]:
Injectment
}
delete
modules
.
include
delete
modules
.
exclude
delete
modules
.
sourceMap
delete
modules
.
devServer
const
modulesMap
=
new
Map
<
string
,
string
|
[
string
,
string
]
>
()
const
namespaceModulesMap
=
new
Map
<
string
,
string
|
[
string
,
string
]
>
()
Object
.
keys
(
modules
).
forEach
((
name
)
=>
{
if
(
name
.
endsWith
(
'
.
'
))
{
namespaceModulesMap
.
set
(
name
,
modules
[
name
])
}
modulesMap
.
set
(
name
,
modules
[
name
])
})
const
hasNamespace
=
namespaceModulesMap
.
size
>
0
// Fix paths on Windows
if
(
sep
!==
'
/
'
)
{
normalizeModulesMap
(
modulesMap
)
normalizeModulesMap
(
namespaceModulesMap
)
}
const
firstpass
=
new
RegExp
(
`(?:
${
Array
.
from
(
modulesMap
.
keys
()).
map
(
escape
).
join
(
'
|
'
)}
)`
,
'
g
'
)
const
EXTNAMES
=
[
'
.js
'
,
'
.ts
'
,
'
.vue
'
,
'
.nvue
'
]
const
sourceMap
=
options
.
sourceMap
!==
false
return
{
name
:
'
uni:inject
'
,
transform
(
code
,
id
)
{
if
(
!
filter
(
id
))
return
null
if
(
!
EXTNAMES
.
includes
(
path
.
extname
(
id
)))
{
return
null
}
debugInjectTry
(
id
)
if
(
code
.
search
(
firstpass
)
===
-
1
)
return
null
if
(
sep
!==
'
/
'
)
id
=
id
.
split
(
sep
).
join
(
'
/
'
)
let
ast
=
null
try
{
ast
=
this
.
parse
(
code
)
}
catch
(
err
)
{
this
.
warn
({
code
:
'
PARSE_ERROR
'
,
message
:
`plugin-inject: failed to parse
${
id
}
. Consider restricting the plugin to particular files via options.include`
,
})
}
if
(
!
ast
)
{
return
null
}
const
imports
=
new
Set
()
;((
ast
as
unknown
)
as
Program
).
body
.
forEach
((
node
)
=>
{
if
(
node
.
type
===
'
ImportDeclaration
'
)
{
node
.
specifiers
.
forEach
((
specifier
)
=>
{
imports
.
add
(
specifier
.
local
.
name
)
})
}
})
// analyse scopes
let
scope
=
attachScopes
(
ast
,
'
scope
'
)
as
Scope
const
magicString
=
new
MagicString
(
code
)
const
newImports
=
new
Map
()
function
handleReference
(
node
:
BaseNode
,
name
:
string
,
keypath
:
string
)
{
let
mod
=
modulesMap
.
get
(
keypath
)
if
(
!
mod
&&
hasNamespace
)
{
const
mods
=
keypath
.
split
(
'
.
'
)
if
(
mods
.
length
===
2
)
{
mod
=
namespaceModulesMap
.
get
(
mods
[
0
]
+
'
.
'
)
if
(
mod
)
{
mod
=
[
mod
as
string
,
mods
[
1
]]
}
}
}
if
(
mod
&&
!
imports
.
has
(
name
)
&&
!
scope
.
contains
(
name
))
{
if
(
typeof
mod
===
'
string
'
)
mod
=
[
mod
,
'
default
'
]
if
(
mod
[
0
]
===
id
)
return
false
const
hash
=
`
${
keypath
}
:
${
mod
[
0
]}
:
${
mod
[
1
]}
`
const
importLocalName
=
name
===
keypath
?
name
:
makeLegalIdentifier
(
`$inject_
${
keypath
}
`
)
if
(
!
newImports
.
has
(
hash
))
{
if
(
mod
[
1
]
===
'
*
'
)
{
newImports
.
set
(
hash
,
`import * as
${
importLocalName
}
from '
${
mod
[
0
]}
';`
)
}
else
{
newImports
.
set
(
hash
,
`import {
${
mod
[
1
]}
as
${
importLocalName
}
} from '
${
mod
[
0
]}
';`
)
}
}
if
(
name
!==
keypath
)
{
magicString
.
overwrite
(
(
node
as
AcornNode
).
start
,
(
node
as
AcornNode
).
end
,
importLocalName
,
{
storeName
:
true
,
}
)
}
return
true
}
return
false
}
walk
(
ast
,
{
enter
(
node
,
parent
)
{
if
(
sourceMap
)
{
magicString
.
addSourcemapLocation
((
node
as
AcornNode
).
start
)
magicString
.
addSourcemapLocation
((
node
as
AcornNode
).
end
)
}
if
((
node
as
any
).
scope
)
{
scope
=
(
node
as
any
).
scope
}
if
(
isProperty
(
node
)
&&
node
.
shorthand
)
{
const
{
name
}
=
node
.
key
as
Identifier
handleReference
(
node
,
name
,
name
)
this
.
skip
()
return
}
if
(
isReference
(
node
,
parent
))
{
const
{
name
,
keypath
}
=
flatten
(
node
)
const
handled
=
handleReference
(
node
,
name
,
keypath
)
if
(
handled
)
{
this
.
skip
()
}
}
},
leave
(
node
)
{
if
((
node
as
any
).
scope
)
{
scope
=
scope
.
parent
}
},
})
debugInject
(
id
,
newImports
.
size
)
if
(
newImports
.
size
===
0
)
{
return
{
code
,
ast
,
map
:
sourceMap
?
magicString
.
generateMap
({
hires
:
true
})
:
null
,
}
}
const
importBlock
=
Array
.
from
(
newImports
.
values
()).
join
(
'
\n\n
'
)
magicString
.
prepend
(
`
${
importBlock
}
\n\n`
)
return
{
code
:
magicString
.
toString
(),
map
:
sourceMap
?
magicString
.
generateMap
({
hires
:
true
})
:
null
,
}
},
}
}
const
escape
=
(
str
:
string
)
=>
str
.
replace
(
/
[
-[
\]/
{}()*+?.
\\
^$|
]
/g
,
'
\\
$&
'
)
const
isProperty
=
(
node
:
BaseNode
):
node
is
Property
=>
node
.
type
===
'
Property
'
const
isIdentifier
=
(
node
:
BaseNode
):
node
is
Identifier
=>
node
.
type
===
'
Identifier
'
const
isMemberExpression
=
(
node
:
BaseNode
):
node
is
MemberExpression
=>
node
.
type
===
'
MemberExpression
'
const
isMethodDefinition
=
(
node
:
BaseNode
):
node
is
MethodDefinition
=>
node
.
type
===
'
MethodDefinition
'
const
isExportSpecifier
=
(
node
:
BaseNode
):
node
is
ExportSpecifier
=>
node
.
type
===
'
ExportSpecifier
'
const
isReference
=
(
node
:
BaseNode
,
parent
:
BaseNode
):
boolean
=>
{
if
(
isMemberExpression
(
node
))
{
return
!
node
.
computed
&&
isReference
(
node
.
object
,
node
)
}
if
(
isIdentifier
(
node
))
{
if
(
isMemberExpression
(
parent
))
return
parent
.
computed
||
node
===
parent
.
object
// `bar` in { bar: foo }
if
(
isProperty
(
parent
)
&&
node
!==
parent
.
value
)
return
false
// `bar` in `class Foo { bar () {...} }`
if
(
isMethodDefinition
(
parent
))
return
false
// `bar` in `export { foo as bar }`
if
(
isExportSpecifier
(
parent
)
&&
node
!==
parent
.
local
)
return
false
return
true
}
return
false
}
const
flatten
=
(
startNode
:
BaseNode
)
=>
{
const
parts
=
[]
let
node
=
startNode
while
(
isMemberExpression
(
node
))
{
parts
.
unshift
((
node
.
property
as
Identifier
).
name
)
node
=
node
.
object
}
const
{
name
}
=
node
as
Identifier
parts
.
unshift
(
name
)
return
{
name
,
keypath
:
parts
.
join
(
'
.
'
)
}
}
function
normalizeModulesMap
(
modulesMap
:
Map
<
string
,
string
|
[
string
,
string
]
>
)
{
modulesMap
.
forEach
((
mod
,
key
)
=>
{
modulesMap
.
set
(
key
,
Array
.
isArray
(
mod
)
?
[
mod
[
0
].
split
(
sep
).
join
(
'
/
'
),
mod
[
1
]]
:
mod
.
split
(
sep
).
join
(
'
/
'
)
)
})
}
packages/vite-plugin-uni/src/configResolved/plugins/pre.ts
浏览文件 @
ae22205f
...
...
@@ -21,11 +21,13 @@ export function uniPrePlugin(options: UniPluginFilterOptions): Plugin {
if
(
!
filter
(
id
))
{
return
code
}
debugPreJsTry
(
id
)
const
extname
=
path
.
extname
(
id
)
const
isHtml
=
PRE_HTML_EXTNAME
.
includes
(
extname
)
const
isJs
=
PRE_JS_EXTNAME
.
includes
(
extname
)
const
isPre
=
isHtml
||
isJs
if
(
isPre
)
{
debugPreJsTry
(
id
)
}
const
hasEndif
=
isPre
&&
code
.
includes
(
'
#endif
'
)
if
(
isHtml
&&
hasEndif
)
{
code
=
preHtml
(
code
)
...
...
packages/vite-plugin-uni/src/configResolved/plugins/preCss.ts
浏览文件 @
ae22205f
...
...
@@ -8,7 +8,7 @@ const { preJs } = require('@dcloudio/uni-cli-shared')
const
debugPre
=
debug
(
'
uni:pre-css
'
)
const
debugPreTry
=
debug
(
'
uni:pre-css-try
'
)
const
cssLangs
=
`\\.(
css|
less|sass|scss|styl|stylus|postcss)($|\\?)`
const
cssLangs
=
`\\.(less|sass|scss|styl|stylus|postcss)($|\\?)`
const
cssLangRE
=
new
RegExp
(
cssLangs
)
/**
* preprocess css
...
...
packages/vite-plugin-uni/src/resolveId.ts
浏览文件 @
ae22205f
...
...
@@ -26,7 +26,7 @@ export function createResolveId(
}
if
(
id
.
startsWith
(
'
@/
'
))
{
debugResolve
(
id
)
return
id
.
replace
(
'
@/
'
,
'
/src/
'
)
return
path
.
join
(
options
.
inputDir
,
id
.
replace
(
'
@/
'
,
''
)
)
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录