@tarojs/rn-runner 3.5.7-alpha.9 → 3.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__tests__/__snapshots__/components.spec.ts.snap +3 -3
- package/__tests__/build.spec.ts +17 -0
- package/__tests__/config.spec.ts +35 -0
- package/dist/config/conditional-file-store.js +57 -0
- package/dist/config/conditional-file-store.js.map +1 -0
- package/dist/config/config-holder.js +76 -0
- package/dist/config/config-holder.js.map +1 -0
- package/dist/config/index.js +57 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/preview.js +102 -0
- package/dist/config/preview.js.map +1 -0
- package/dist/config/terminal-reporter.js +103 -0
- package/dist/config/terminal-reporter.js.map +1 -0
- package/dist/index.js +184 -81
- package/dist/index.js.map +1 -1
- package/dist/utils.js +29 -0
- package/dist/utils.js.map +1 -0
- package/package.json +24 -11
- package/src/config/conditional-file-store.ts +47 -0
- package/src/config/config-holder.ts +70 -0
- package/src/config/index.ts +76 -0
- package/src/config/preview.ts +114 -0
- package/src/config/terminal-reporter.ts +96 -0
- package/src/index.ts +206 -80
- package/src/utils.ts +27 -0
- package/templates/index.js +0 -1
- package/templates/metro.config.js +0 -8
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { readFile } from 'fs'
|
|
2
|
+
import { createServer } from 'http'
|
|
3
|
+
import * as mime from 'mime-types'
|
|
4
|
+
import { extname, join } from 'path'
|
|
5
|
+
import * as qr from 'qrcode-terminal'
|
|
6
|
+
import { URL } from 'url'
|
|
7
|
+
|
|
8
|
+
import { getOpenHost, isWin, PLAYGROUNDINFO } from '../utils'
|
|
9
|
+
|
|
10
|
+
interface PreviewOption {
|
|
11
|
+
out: string
|
|
12
|
+
platform: string
|
|
13
|
+
assetsDest?: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const drawableFileTypes = new Set<string>([
|
|
17
|
+
'gif',
|
|
18
|
+
'jpeg',
|
|
19
|
+
'jpg',
|
|
20
|
+
'png',
|
|
21
|
+
'webp',
|
|
22
|
+
'xml'
|
|
23
|
+
])
|
|
24
|
+
|
|
25
|
+
function getAndroidAssetSuffix (scale: number): string {
|
|
26
|
+
switch (scale) {
|
|
27
|
+
case 0.75:
|
|
28
|
+
return 'ldpi'
|
|
29
|
+
case 1:
|
|
30
|
+
return 'mdpi'
|
|
31
|
+
case 1.5:
|
|
32
|
+
return 'hdpi'
|
|
33
|
+
case 2:
|
|
34
|
+
return 'xhdpi'
|
|
35
|
+
case 3:
|
|
36
|
+
return 'xxhdpi'
|
|
37
|
+
case 4:
|
|
38
|
+
return 'xxxhdpi'
|
|
39
|
+
default:
|
|
40
|
+
return ''
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function getAndroidResourceFolderName (pathname:string): string {
|
|
45
|
+
const ext = extname(pathname).replace(/^./, '').toLowerCase()
|
|
46
|
+
if (!drawableFileTypes.has(ext)) {
|
|
47
|
+
return 'raw'
|
|
48
|
+
}
|
|
49
|
+
const suffix = getAndroidAssetSuffix(1) // TODO: auto scale
|
|
50
|
+
const androidFolder = `drawable-${suffix}`
|
|
51
|
+
return androidFolder
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function getAndroidResourceIdentifier (pathname:string): string {
|
|
55
|
+
if (pathname[0] === '/') {
|
|
56
|
+
pathname = pathname.substr(1)
|
|
57
|
+
}
|
|
58
|
+
const ext = extname(pathname).toLowerCase()
|
|
59
|
+
const extReg = new RegExp(ext + '$')
|
|
60
|
+
return pathname
|
|
61
|
+
.replace(extReg, '')
|
|
62
|
+
.toLowerCase()
|
|
63
|
+
.replace(/\//g, '_')
|
|
64
|
+
.replace(/([^a-z0-9_])/g, '')
|
|
65
|
+
.replace(/^assets_/, '') + ext
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export default (opt: PreviewOption):void => {
|
|
69
|
+
const port = process.env.PORT || 8079
|
|
70
|
+
const host = `http://${getOpenHost()}:${port}`
|
|
71
|
+
|
|
72
|
+
createServer(function (request, response) {
|
|
73
|
+
const url = new URL(request.url || '', host)
|
|
74
|
+
|
|
75
|
+
console.log(`${request.method} ${request.url}`)
|
|
76
|
+
|
|
77
|
+
if (url.pathname === '/inspector/device') {
|
|
78
|
+
response.writeHead(404)
|
|
79
|
+
response.end('404', 'utf-8')
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let filePath
|
|
84
|
+
const contentType = mime.lookup(url.pathname)
|
|
85
|
+
|
|
86
|
+
if (url.pathname === '/index.js') {
|
|
87
|
+
filePath = opt.out
|
|
88
|
+
} else if (opt.platform === 'ios') {
|
|
89
|
+
filePath = join(opt.assetsDest || '', url.pathname)
|
|
90
|
+
} else if (opt.platform === 'android') {
|
|
91
|
+
filePath = join(opt.assetsDest || '', getAndroidResourceFolderName(url.pathname), getAndroidResourceIdentifier(url.pathname))
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
readFile(filePath, function (error, content) {
|
|
95
|
+
if (error) {
|
|
96
|
+
if (error.code === 'ENOENT') {
|
|
97
|
+
response.writeHead(404)
|
|
98
|
+
response.end('404', 'utf-8')
|
|
99
|
+
} else {
|
|
100
|
+
response.writeHead(500)
|
|
101
|
+
response.end('500', 'utf-8')
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
response.writeHead(200, { 'Content-Type': contentType })
|
|
105
|
+
response.end(content, 'utf-8')
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
}).listen(port)
|
|
109
|
+
|
|
110
|
+
const url = `${host}/index.js`
|
|
111
|
+
console.log(PLAYGROUNDINFO)
|
|
112
|
+
console.log(`print qrcode of ${opt.platform} bundle '${url}':`)
|
|
113
|
+
qr.generate(url, { small: !isWin })
|
|
114
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { emptyModulePath } from '@tarojs/rn-supporter'
|
|
2
|
+
import * as MetroTerminalReporter from 'metro/src/lib/TerminalReporter'
|
|
3
|
+
import { Terminal } from 'metro-core'
|
|
4
|
+
|
|
5
|
+
export class TerminalReporter {
|
|
6
|
+
_reporter: any
|
|
7
|
+
_conditionalFileStore: any
|
|
8
|
+
metroServerInstance: any
|
|
9
|
+
_initialized: boolean
|
|
10
|
+
_entry: string
|
|
11
|
+
_sourceRoot: string
|
|
12
|
+
|
|
13
|
+
constructor (entry: string, sourceRoot: string, conditionalFileStore: any, metroServerInstance?: any) {
|
|
14
|
+
this._reporter = new MetroTerminalReporter(new Terminal(process.stdout))
|
|
15
|
+
this._conditionalFileStore = conditionalFileStore
|
|
16
|
+
this.metroServerInstance = metroServerInstance
|
|
17
|
+
this._initialized = false
|
|
18
|
+
this._entry = entry
|
|
19
|
+
this._sourceRoot = sourceRoot
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async update (args) {
|
|
23
|
+
// 当依赖图加载之后,检测app和页面配置文件的变化
|
|
24
|
+
switch (args.type) {
|
|
25
|
+
case 'initialize_started':
|
|
26
|
+
this._reporter.terminal.log(`
|
|
27
|
+
##### ## ##### #### ##### ###### ## #### ##### # # ## ##### # # # ######
|
|
28
|
+
# # # # # # # # # # # # # # # ## # # # # # # # #
|
|
29
|
+
# # # # # # # # # ##### # # # # # # # # # # # # # #####
|
|
30
|
+
# ###### ##### # # ##### # ###### # # # # # ###### # # # # #
|
|
31
|
+
# # # # # # # # # # # # # # # # ## # # # # # # #
|
|
32
|
+
# # # # # #### # # ###### # # #### # # # # # # # ## ######
|
|
33
|
+
`)
|
|
34
|
+
break
|
|
35
|
+
case 'bundle_build_started':
|
|
36
|
+
args.bundleDetails.entryFile = './index'
|
|
37
|
+
this._reporter.update(args)
|
|
38
|
+
break
|
|
39
|
+
case 'bundle_build_done': {
|
|
40
|
+
this._reporter.update(args)
|
|
41
|
+
const realEntryPath = require.resolve(emptyModulePath)
|
|
42
|
+
if (this._initialized) {
|
|
43
|
+
// 恢复入口页面的缓存
|
|
44
|
+
this._reporter.ignoreEntryFileCache = false
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
this._initialized = true
|
|
48
|
+
if (!this.metroServerInstance) {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
const incrementalBundler = this.metroServerInstance.getBundler()
|
|
52
|
+
const deltaBundler = incrementalBundler.getDeltaBundler()
|
|
53
|
+
const bundler = incrementalBundler.getBundler()
|
|
54
|
+
const findEntryGraphId = keys => {
|
|
55
|
+
for (const k of keys) {
|
|
56
|
+
if (JSON.parse(k).entryFile === realEntryPath) {
|
|
57
|
+
return k
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return null
|
|
61
|
+
}
|
|
62
|
+
// 获取入口文件的graph
|
|
63
|
+
const entryGraphId = findEntryGraphId(incrementalBundler._revisionsByGraphId.keys())
|
|
64
|
+
const entryGraphVersion = await incrementalBundler.getRevisionByGraphId(entryGraphId)
|
|
65
|
+
|
|
66
|
+
// 监听DeltaCalculator的change事件,把入口文件也加入到_modifiedFiles集合中
|
|
67
|
+
bundler.getDependencyGraph().then(dependencyGraph => {
|
|
68
|
+
dependencyGraph.getWatcher().on('change', ({ eventsQueue }) => {
|
|
69
|
+
const changedFiles = eventsQueue.map(item => item.filePath)
|
|
70
|
+
// 如果配置文件修改之后,把入口文件添加到修改列表中
|
|
71
|
+
const deltaCalculator = deltaBundler._deltaCalculators.get(entryGraphVersion.graph)
|
|
72
|
+
const isConfigurationModified = keys => {
|
|
73
|
+
for (const k of keys) {
|
|
74
|
+
if (k.includes('.config') && k.includes(this._sourceRoot)) {
|
|
75
|
+
return true
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return false
|
|
79
|
+
}
|
|
80
|
+
if (isConfigurationModified(changedFiles)) {
|
|
81
|
+
// 忽略入口文件的转译结果缓存
|
|
82
|
+
this._conditionalFileStore.ignoreEntryFileCache = true
|
|
83
|
+
deltaCalculator._modifiedFiles.add(realEntryPath)
|
|
84
|
+
this._reporter.terminal.flush()
|
|
85
|
+
console.log('\nConfiguration(s) are changed.')
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
break
|
|
91
|
+
default:
|
|
92
|
+
this._reporter.update(args)
|
|
93
|
+
break
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,44 +1,104 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import saveAssets from '@react-native-community/cli-plugin-metro/build/commands/bundle/saveAssets'
|
|
2
|
+
import { createDevServerMiddleware } from '@react-native-community/cli-server-api'
|
|
3
|
+
import { PLATFORMS } from '@tarojs/helper'
|
|
4
4
|
import * as fse from 'fs-extra'
|
|
5
|
-
import
|
|
5
|
+
import * as Metro from 'metro'
|
|
6
|
+
import { getResolveDependencyFn } from 'metro/src/lib/transformHelpers'
|
|
7
|
+
import * as Server from 'metro/src/Server'
|
|
8
|
+
import * as outputBundle from 'metro/src/shared/output/bundle'
|
|
9
|
+
import * as path from 'path'
|
|
10
|
+
import * as qr from 'qrcode-terminal'
|
|
11
|
+
import * as readline from 'readline'
|
|
12
|
+
import * as url from 'url'
|
|
6
13
|
|
|
14
|
+
import getMetroConfig from './config'
|
|
7
15
|
import buildComponent from './config/build-component'
|
|
16
|
+
import { getRNConfigEntry } from './config/config-holder'
|
|
17
|
+
import preview from './config/preview'
|
|
18
|
+
import { TerminalReporter } from './config/terminal-reporter'
|
|
19
|
+
import { getOpenHost, isWin, PLAYGROUNDINFO } from './utils'
|
|
8
20
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
} else {
|
|
21
|
-
console.log(`${file} created`)
|
|
21
|
+
function concatOutputFileName (config: any): string {
|
|
22
|
+
// 优先级:--bundle-output > config.output > config.outputRoot
|
|
23
|
+
let output = path.join(config.outputRoot, 'index.bundle')
|
|
24
|
+
if (config.output) {
|
|
25
|
+
const outputType = typeof config.output
|
|
26
|
+
if (outputType === 'string') {
|
|
27
|
+
output = config.output
|
|
28
|
+
} else if (outputType === 'object') {
|
|
29
|
+
output = config.output[config.deviceType]
|
|
30
|
+
if (!output) {
|
|
31
|
+
console.error(`lack value for 'rn.output' configuration with platform '${config.deviceType}': ${JSON.stringify(config.output)}`)
|
|
22
32
|
}
|
|
23
|
-
}
|
|
24
|
-
|
|
33
|
+
} else {
|
|
34
|
+
console.error(`invalid value for 'rn.output' configuration: ${JSON.stringify(config.output)}`)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (config.bundleOutput) {
|
|
38
|
+
output = config.bundleOutput
|
|
39
|
+
}
|
|
40
|
+
const res = path.isAbsolute(output) ? output : path.join('.', output)
|
|
41
|
+
fse.ensureDirSync(path.dirname(res))
|
|
42
|
+
return res
|
|
25
43
|
}
|
|
26
44
|
|
|
27
|
-
|
|
28
|
-
|
|
45
|
+
function concatOutputAssetsDest (config: any): string | undefined {
|
|
46
|
+
// 优先级:--assets-dest > config.output > config.outputRoot
|
|
47
|
+
let assetDest
|
|
48
|
+
if (!config?.deviceType || !config?.output) {
|
|
49
|
+
assetDest = config.outputRoot
|
|
50
|
+
} else {
|
|
51
|
+
assetDest = config.deviceType === 'ios' ? config.output.iosAssetsDest : config.output.androidAssetsDest
|
|
52
|
+
}
|
|
53
|
+
if (config.assetsDest) {
|
|
54
|
+
assetDest = config.assetsDest
|
|
55
|
+
}
|
|
56
|
+
if (!assetDest) return undefined
|
|
57
|
+
const res = path.isAbsolute(assetDest) ? assetDest : path.join('.', assetDest)
|
|
58
|
+
fse.ensureDirSync(path.dirname(res))
|
|
59
|
+
return res
|
|
60
|
+
}
|
|
29
61
|
|
|
30
|
-
|
|
31
|
-
|
|
62
|
+
function getOutputSourceMapOption (config: any): Record<string, any> {
|
|
63
|
+
if (!config?.deviceType) {
|
|
64
|
+
return {}
|
|
65
|
+
}
|
|
32
66
|
const isIos = config.deviceType === 'ios'
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
67
|
+
const sourceMapUrl = config.sourceMapUrl || (isIos ? config?.output?.iosSourceMapUrl : config?.output?.androidSourceMapUrl)
|
|
68
|
+
const sourcemapOutput = config.sourcemapOutput || (isIos ? config?.output?.iosSourcemapOutput : config?.output?.androidSourcemapOutput)
|
|
69
|
+
const sourcemapSourcesRoot = config.sourcemapSourcesRoot || (isIos ? config?.output?.iosSourcemapSourcesRoot : config?.output?.androidSourcemapSourcesRoot)
|
|
70
|
+
sourcemapOutput && fse.ensureDirSync(path.dirname(sourcemapOutput))
|
|
71
|
+
return {
|
|
72
|
+
sourceMapUrl,
|
|
73
|
+
sourcemapOutput,
|
|
74
|
+
sourcemapSourcesRoot
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// TODO: 返回值
|
|
79
|
+
// HttpServer | {code: string, map: string}
|
|
80
|
+
// IBuildConfig
|
|
81
|
+
export default async function build (_appPath: string, config: any): Promise<any> {
|
|
82
|
+
process.env.TARO_ENV = PLATFORMS.RN
|
|
83
|
+
// TODO:新增环境变量是否可以在metro构建过程中可以访问到?
|
|
84
|
+
const entry = getRNConfigEntry()
|
|
85
|
+
config.entry = entry
|
|
86
|
+
const metroConfig = await getMetroConfig(config)
|
|
87
|
+
const sourceRoot = config.sourceRoot || 'src'
|
|
88
|
+
|
|
89
|
+
const commonOptions = {
|
|
90
|
+
platform: config.deviceType,
|
|
91
|
+
minify: process.env.NODE_ENV === 'production' || !config.isWatch,
|
|
92
|
+
dev: config.isWatch
|
|
93
|
+
}
|
|
36
94
|
if (config.resetCache) {
|
|
37
|
-
|
|
95
|
+
metroConfig.resetCache = config.resetCache
|
|
38
96
|
}
|
|
39
97
|
if (config.publicPath) {
|
|
40
|
-
|
|
98
|
+
metroConfig.transformer.publicPath = config.publicPath
|
|
41
99
|
}
|
|
100
|
+
metroConfig.reporter = new TerminalReporter(entry, sourceRoot, metroConfig.cacheStores[0])
|
|
101
|
+
|
|
42
102
|
const onFinish = function (error?) {
|
|
43
103
|
if (typeof config.onBuildFinish === 'function') {
|
|
44
104
|
config.onBuildFinish({
|
|
@@ -48,79 +108,145 @@ export default async function build (_appPath: string, config: any): Promise<any
|
|
|
48
108
|
}
|
|
49
109
|
if (error instanceof Error) throw error
|
|
50
110
|
}
|
|
111
|
+
|
|
51
112
|
if (config.isBuildNativeComp) {
|
|
52
113
|
return buildComponent(
|
|
53
114
|
_appPath,
|
|
54
115
|
config
|
|
55
116
|
)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
117
|
+
} else if (config.isWatch) {
|
|
118
|
+
if (!metroConfig.server || (metroConfig.server.useGlobalHotkey === undefined)) {
|
|
119
|
+
if (!metroConfig.server) {
|
|
120
|
+
metroConfig.server = {}
|
|
121
|
+
}
|
|
122
|
+
metroConfig.server.useGlobalHotkey = true
|
|
123
|
+
}
|
|
59
124
|
if (config.port) {
|
|
60
|
-
|
|
125
|
+
metroConfig.server.port = config.port
|
|
61
126
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
127
|
+
|
|
128
|
+
const {
|
|
129
|
+
middleware,
|
|
130
|
+
messageSocketEndpoint,
|
|
131
|
+
websocketEndpoints
|
|
132
|
+
} = createDevServerMiddleware({
|
|
133
|
+
port: metroConfig.server.port,
|
|
134
|
+
watchFolders: metroConfig.watchFolders
|
|
135
|
+
})
|
|
136
|
+
metroConfig.server.enhanceMiddleware = (metroMiddleware, metroServer) => {
|
|
137
|
+
metroConfig.reporter.metroServerInstance = metroServer
|
|
138
|
+
|
|
139
|
+
// bundle路由只识别/index.bundle
|
|
140
|
+
return middleware.use((req, res, next) => {
|
|
141
|
+
// eslint-disable-next-line node/no-deprecated-api
|
|
142
|
+
const urlObj = url.parse(req.url)
|
|
143
|
+
if (/\/[^]+.bundle/.test(urlObj.pathname || '') && (urlObj.pathname || '').toLowerCase() !== '/index.bundle') {
|
|
144
|
+
res.writeHead(400)
|
|
145
|
+
res.end('Please access /index.bundle for entry bundling.')
|
|
146
|
+
} else if (/^\/debugger-ui\//.test(urlObj.pathname || '')) {
|
|
147
|
+
next()
|
|
148
|
+
} else {
|
|
149
|
+
metroMiddleware(req, res, next)
|
|
150
|
+
}
|
|
65
151
|
})
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 支持host
|
|
155
|
+
return Metro.runServer(metroConfig, {
|
|
156
|
+
...commonOptions,
|
|
157
|
+
hmrEnabled: true,
|
|
158
|
+
websocketEndpoints
|
|
159
|
+
}).then(server => {
|
|
160
|
+
console.log(`React-Native Dev server is running on port: ${metroConfig.server.port}`)
|
|
161
|
+
console.log('\n\nTo reload the app press "r"\nTo open developer menu press "d"\n')
|
|
162
|
+
|
|
163
|
+
readline.emitKeypressEvents(process.stdin)
|
|
164
|
+
process.stdin.setRawMode && process.stdin.setRawMode(true)
|
|
165
|
+
process.stdin.on('keypress', (_key, data) => {
|
|
166
|
+
const { ctrl, name } = data
|
|
167
|
+
if (name === 'r') {
|
|
168
|
+
messageSocketEndpoint.broadcast('reload')
|
|
169
|
+
console.log('Reloading app...')
|
|
170
|
+
} else if (name === 'd') {
|
|
171
|
+
messageSocketEndpoint.broadcast('devMenu')
|
|
172
|
+
console.log('Opening developer menu...')
|
|
173
|
+
} else if (ctrl && (name === 'c')) {
|
|
174
|
+
process.exit()
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
if (config.qr) {
|
|
179
|
+
const host = getOpenHost()
|
|
180
|
+
if (host) {
|
|
181
|
+
const url = `taro://${host}:${metroConfig.server.port}`
|
|
182
|
+
console.log(PLAYGROUNDINFO)
|
|
183
|
+
console.log(`print qrcode of '${url}':`)
|
|
184
|
+
qr.generate(url, { small: !isWin })
|
|
185
|
+
} else {
|
|
186
|
+
console.log('print qrcode error: host not found.')
|
|
187
|
+
}
|
|
70
188
|
}
|
|
71
189
|
onFinish(null)
|
|
72
|
-
|
|
190
|
+
return server
|
|
191
|
+
}).catch(e => {
|
|
73
192
|
onFinish(e)
|
|
74
|
-
}
|
|
193
|
+
})
|
|
75
194
|
} else {
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
cliParams.push('--bundle-output', bundleOutput)
|
|
81
|
-
|
|
82
|
-
const sourcemapOutput = config.sourcemapOutput ? config.sourcemapOutput : (isIos ? config.output.iosSourcemapOutput : config.output.androidSourcemapOutput)
|
|
83
|
-
if (sourcemapOutput) {
|
|
84
|
-
cliParams.push('--sourcemap-output', sourcemapOutput)
|
|
195
|
+
const options = {
|
|
196
|
+
...commonOptions,
|
|
197
|
+
entry: './index',
|
|
198
|
+
out: concatOutputFileName(config)
|
|
85
199
|
}
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
200
|
+
const savedBuildFunc = outputBundle.build
|
|
201
|
+
outputBundle.build = async (packagerClient, requestOptions) => {
|
|
202
|
+
const resolutionFn = await getResolveDependencyFn(packagerClient.getBundler().getBundler(), requestOptions.platform)
|
|
203
|
+
// try for test case build_noWatch
|
|
204
|
+
try {
|
|
205
|
+
requestOptions.entryFile = resolutionFn(metroConfig.projectRoot, requestOptions.entryFile)
|
|
206
|
+
} catch (e) {} // eslint-disable-line no-empty
|
|
207
|
+
return savedBuildFunc(packagerClient, requestOptions)
|
|
89
208
|
}
|
|
90
209
|
|
|
91
|
-
const
|
|
92
|
-
if (sourcemapSourcesRoot) {
|
|
93
|
-
cliParams.push('--sourcemap-sources-root', sourcemapSourcesRoot)
|
|
94
|
-
}
|
|
210
|
+
const server = new Server(metroConfig)
|
|
95
211
|
|
|
96
|
-
const
|
|
97
|
-
cliParams.push('--assets-dest', assetsDest)
|
|
212
|
+
const sourceMapOption = getOutputSourceMapOption(config)
|
|
98
213
|
|
|
99
214
|
try {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
215
|
+
const requestOptions = {
|
|
216
|
+
...commonOptions,
|
|
217
|
+
...sourceMapOption,
|
|
218
|
+
entryFile: options.entry,
|
|
219
|
+
inlineSourceMap: false,
|
|
220
|
+
createModuleIdFactory: metroConfig.serializer.createModuleIdFactory
|
|
221
|
+
}
|
|
222
|
+
const bundle = await outputBundle.build(server, requestOptions)
|
|
223
|
+
const outputOptions = {
|
|
224
|
+
...commonOptions,
|
|
225
|
+
...sourceMapOption,
|
|
226
|
+
bundleOutput: options.out
|
|
227
|
+
}
|
|
228
|
+
await outputBundle.save(bundle, outputOptions, console.log)
|
|
229
|
+
|
|
230
|
+
// Save the assets of the bundle
|
|
231
|
+
const outputAssets = await server.getAssets({
|
|
232
|
+
...Server.DEFAULT_BUNDLE_OPTIONS,
|
|
233
|
+
...requestOptions
|
|
111
234
|
})
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
assetsDest
|
|
235
|
+
const assetsDest = concatOutputAssetsDest(config)
|
|
236
|
+
return await saveAssets(outputAssets, options.platform, assetsDest).then(() => {
|
|
237
|
+
if (config.qr) {
|
|
238
|
+
preview({
|
|
239
|
+
out: options.out,
|
|
240
|
+
assetsDest,
|
|
241
|
+
platform: options.platform
|
|
118
242
|
})
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
} catch(e) {
|
|
243
|
+
}
|
|
244
|
+
onFinish(null)
|
|
245
|
+
})
|
|
246
|
+
} catch (e) {
|
|
123
247
|
onFinish(e)
|
|
248
|
+
} finally {
|
|
249
|
+
server.end()
|
|
124
250
|
}
|
|
125
251
|
}
|
|
126
252
|
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { networkInterfaces } from 'os'
|
|
2
|
+
|
|
3
|
+
export function getOpenHost () {
|
|
4
|
+
let result
|
|
5
|
+
const interfaces = networkInterfaces()
|
|
6
|
+
for (const devName in interfaces) {
|
|
7
|
+
const isEnd = interfaces[devName]?.some(item => {
|
|
8
|
+
// 取IPv4, 不为127.0.0.1的内网ip
|
|
9
|
+
if (['IPv4', 4, '4'].includes(item.family) && item.address !== '127.0.0.1' && !item.internal) {
|
|
10
|
+
result = item.address
|
|
11
|
+
return true
|
|
12
|
+
}
|
|
13
|
+
return false
|
|
14
|
+
})
|
|
15
|
+
// 若获取到ip, 结束遍历
|
|
16
|
+
if (isEnd) {
|
|
17
|
+
break
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return result
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const PLAYGROUNDREPO = 'https://github.com/wuba/taro-playground'
|
|
24
|
+
|
|
25
|
+
export const PLAYGROUNDINFO = `use [Taro Playground App](${PLAYGROUNDREPO}) to scan`
|
|
26
|
+
|
|
27
|
+
export const isWin = /^win/.test(process.platform)
|
package/templates/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import '@tarojs/rn-supporter/entry-file.js'
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
const { mergeConfig } = require('metro-config')
|
|
2
|
-
const { getMetroConfig } = require('@tarojs/rn-supporter')
|
|
3
|
-
|
|
4
|
-
module.exports = mergeConfig({
|
|
5
|
-
// custom your metro config here
|
|
6
|
-
// https://facebook.github.io/metro/docs/configuration
|
|
7
|
-
resolver: {}
|
|
8
|
-
}, getMetroConfig())
|