@ray-js/builder-mp 0.3.0-beta.1c347991
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/lib/Builder.d.ts +11 -0
- package/lib/Builder.js +22 -0
- package/lib/babel-plugins/ray-hooks/index.d.ts +14 -0
- package/lib/babel-plugins/ray-hooks/index.js +63 -0
- package/lib/babel-plugins/ray-page-context/__fixtures__/page-anonymous-fn/code.config.d.ts +3 -0
- package/lib/babel-plugins/ray-page-context/__fixtures__/page-anonymous-fn/code.config.js +6 -0
- package/lib/babel-plugins/ray-page-context/__fixtures__/page-fn/code.config.d.ts +3 -0
- package/lib/babel-plugins/ray-page-context/__fixtures__/page-fn/code.config.js +6 -0
- package/lib/babel-plugins/ray-page-context/__fixtures__/page-instance/code.config.d.ts +3 -0
- package/lib/babel-plugins/ray-page-context/__fixtures__/page-instance/code.config.js +6 -0
- package/lib/babel-plugins/ray-page-context/__fixtures__/single/code.config.d.ts +3 -0
- package/lib/babel-plugins/ray-page-context/__fixtures__/single/code.config.js +6 -0
- package/lib/babel-plugins/ray-page-context/app.config.d.ts +3 -0
- package/lib/babel-plugins/ray-page-context/app.config.js +6 -0
- package/lib/babel-plugins/ray-page-context/index.d.ts +17 -0
- package/lib/babel-plugins/ray-page-context/index.js +258 -0
- package/lib/build.d.ts +5 -0
- package/lib/build.js +224 -0
- package/lib/configs/babel.config.d.ts +12 -0
- package/lib/configs/babel.config.js +18 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +8 -0
- package/lib/webpack-plugins/AppFrameworkEntry/index.d.ts +13 -0
- package/lib/webpack-plugins/AppFrameworkEntry/index.js +49 -0
- package/package.json +69 -0
package/lib/Builder.d.ts
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
import { Entry } from 'webpack';
|
2
|
+
import { CliOptions } from '@ray-js/types';
|
3
|
+
export default class Builder {
|
4
|
+
private cliOptions;
|
5
|
+
private entryValue;
|
6
|
+
get options(): CliOptions;
|
7
|
+
set options(v: CliOptions);
|
8
|
+
get entry(): Entry;
|
9
|
+
set entry(v: Entry);
|
10
|
+
}
|
11
|
+
export declare const builder: Builder;
|
package/lib/Builder.js
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.builder = void 0;
|
4
|
+
class Builder {
|
5
|
+
constructor() {
|
6
|
+
this.entryValue = {};
|
7
|
+
}
|
8
|
+
get options() {
|
9
|
+
return this.cliOptions;
|
10
|
+
}
|
11
|
+
set options(v) {
|
12
|
+
this.cliOptions = v;
|
13
|
+
}
|
14
|
+
get entry() {
|
15
|
+
return this.entryValue;
|
16
|
+
}
|
17
|
+
set entry(v) {
|
18
|
+
this.entryValue = v;
|
19
|
+
}
|
20
|
+
}
|
21
|
+
exports.default = Builder;
|
22
|
+
exports.builder = new Builder();
|
@@ -0,0 +1,14 @@
|
|
1
|
+
/**
|
2
|
+
* 1. 替换 usePageEvent 到 @remax/macro
|
3
|
+
*/
|
4
|
+
import { NodePath } from '@babel/traverse';
|
5
|
+
import * as t from '@babel/types';
|
6
|
+
/**
|
7
|
+
* web 构建模式加, 替换到 ray 的运行时 API
|
8
|
+
* @constructor
|
9
|
+
*/
|
10
|
+
export default function RayHooks(): {
|
11
|
+
visitor: {
|
12
|
+
ImportSpecifier(path: NodePath<t.ImportSpecifier>, state: any): void;
|
13
|
+
};
|
14
|
+
};
|
@@ -0,0 +1,63 @@
|
|
1
|
+
"use strict";
|
2
|
+
/**
|
3
|
+
* 1. 替换 usePageEvent 到 @remax/macro
|
4
|
+
*/
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
6
|
+
if (k2 === undefined) k2 = k;
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
10
|
+
}
|
11
|
+
Object.defineProperty(o, k2, desc);
|
12
|
+
}) : (function(o, m, k, k2) {
|
13
|
+
if (k2 === undefined) k2 = k;
|
14
|
+
o[k2] = m[k];
|
15
|
+
}));
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
18
|
+
}) : function(o, v) {
|
19
|
+
o["default"] = v;
|
20
|
+
});
|
21
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
22
|
+
if (mod && mod.__esModule) return mod;
|
23
|
+
var result = {};
|
24
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
25
|
+
__setModuleDefault(result, mod);
|
26
|
+
return result;
|
27
|
+
};
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
29
|
+
const t = __importStar(require("@babel/types"));
|
30
|
+
function insertImport(program, imports, moduleName) {
|
31
|
+
const specifiers = imports.map((i) => t.importSpecifier(t.identifier(i), t.identifier(i)));
|
32
|
+
const importDeclaration = t.importDeclaration(specifiers, t.stringLiteral(moduleName));
|
33
|
+
program.unshiftContainer('body', importDeclaration);
|
34
|
+
}
|
35
|
+
/**
|
36
|
+
* web 构建模式加, 替换到 ray 的运行时 API
|
37
|
+
* @constructor
|
38
|
+
*/
|
39
|
+
function RayHooks() {
|
40
|
+
return {
|
41
|
+
visitor: {
|
42
|
+
ImportSpecifier(path, state) {
|
43
|
+
const program = state.file.path;
|
44
|
+
const { node } = path;
|
45
|
+
const name = node.local.name;
|
46
|
+
if (['usePageEvent', 'useAppEvent'].includes(name) &&
|
47
|
+
t.isImportDeclaration(path.parentPath)) {
|
48
|
+
const { node } = path.parentPath;
|
49
|
+
if (node.source.value === 'ray') {
|
50
|
+
if (node.specifiers.length > 1) {
|
51
|
+
path.remove();
|
52
|
+
insertImport(program, [name], `@remax/macro`);
|
53
|
+
}
|
54
|
+
else {
|
55
|
+
node.source.value = '@remax/macro';
|
56
|
+
}
|
57
|
+
}
|
58
|
+
}
|
59
|
+
},
|
60
|
+
},
|
61
|
+
};
|
62
|
+
}
|
63
|
+
exports.default = RayHooks;
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { NodePath } from '@babel/traverse';
|
2
|
+
import * as t from '@babel/types';
|
3
|
+
/**
|
4
|
+
* 1. 增加小程序运行时 context appConfig pageConfig 的导入, 并共享到 PageInstanceContext 上
|
5
|
+
* 2. 或增加 withPage 的依赖项
|
6
|
+
* 3. 早于 ray-hooks 执行
|
7
|
+
* @param _ babel
|
8
|
+
* @param options compileOptions
|
9
|
+
* @constructor
|
10
|
+
*/
|
11
|
+
export default function ContextAndHoc(): {
|
12
|
+
pre(state: any): void;
|
13
|
+
visitor: {
|
14
|
+
ExportDefaultDeclaration(path: NodePath<t.ExportDefaultDeclaration>, state: any): void;
|
15
|
+
};
|
16
|
+
post(state: any): void;
|
17
|
+
};
|
@@ -0,0 +1,258 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
+
}
|
8
|
+
Object.defineProperty(o, k2, desc);
|
9
|
+
}) : (function(o, m, k, k2) {
|
10
|
+
if (k2 === undefined) k2 = k;
|
11
|
+
o[k2] = m[k];
|
12
|
+
}));
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
15
|
+
}) : function(o, v) {
|
16
|
+
o["default"] = v;
|
17
|
+
});
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
19
|
+
if (mod && mod.__esModule) return mod;
|
20
|
+
var result = {};
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
22
|
+
__setModuleDefault(result, mod);
|
23
|
+
return result;
|
24
|
+
};
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
27
|
+
};
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
29
|
+
const change_case_1 = require("change-case");
|
30
|
+
const fs_1 = __importDefault(require("fs"));
|
31
|
+
const P = __importStar(require("path"));
|
32
|
+
const slash_1 = __importDefault(require("slash"));
|
33
|
+
const template_1 = __importDefault(require("@babel/template"));
|
34
|
+
const t = __importStar(require("@babel/types"));
|
35
|
+
const shared_1 = require("@ray-js/shared");
|
36
|
+
const Builder_1 = require("../../Builder");
|
37
|
+
function insertSpecifierImport(program, imports, moduleName) {
|
38
|
+
const specifiers = imports.map((i) => t.importSpecifier(t.identifier(i), t.identifier(i)));
|
39
|
+
const importDeclaration = t.importDeclaration(specifiers, t.stringLiteral(moduleName));
|
40
|
+
program.unshiftContainer('body', importDeclaration);
|
41
|
+
}
|
42
|
+
const contextTemplate = (0, template_1.default)(`const id = forwardRef((props, ref) => {
|
43
|
+
const isClassType = (c) => c.prototype && typeof c.prototype.render === 'function';
|
44
|
+
const $instance = new PageInstance();
|
45
|
+
usePageEvent('onLoad', () => {
|
46
|
+
lifecycle.addInstance($instance);
|
47
|
+
lifecycle.emit({ name: 'onLoad', uniqueId: $instance.uniqueId })
|
48
|
+
});
|
49
|
+
usePageEvent('onUnload', () => {
|
50
|
+
lifecycle.emit({ name: 'onUnload', uniqueId: $instance.uniqueId })
|
51
|
+
lifecycle.removeInstance($instance);
|
52
|
+
});
|
53
|
+
usePageEvent('onShow', () => {
|
54
|
+
lifecycle.emit({ name: 'onShow', uniqueId: $instance.uniqueId })
|
55
|
+
});
|
56
|
+
return (
|
57
|
+
<PageInstanceContext.Provider value={{
|
58
|
+
$instance: $instance,
|
59
|
+
}}
|
60
|
+
>
|
61
|
+
{isClassType(compName) ? <compTag ref={ref} {...props}/> : <compTag {...props}/> }
|
62
|
+
</PageInstanceContext.Provider>
|
63
|
+
);
|
64
|
+
});`, {
|
65
|
+
plugins: ['jsx'],
|
66
|
+
syntacticPlaceholders: false,
|
67
|
+
placeholderWhitelist: new Set(['id', 'compTag', 'compName', 'platform']),
|
68
|
+
placeholderPattern: false,
|
69
|
+
});
|
70
|
+
const pageConfigTemplate = (0, template_1.default)(`const __pageConfig = require("file");
|
71
|
+
const __pageConfigData = __pageConfig.platform ? {...__pageConfig.platform} : __pageConfig.default ? {...__pageConfig.default} : {}
|
72
|
+
`, {
|
73
|
+
syntacticPlaceholders: false,
|
74
|
+
placeholderWhitelist: new Set(['file', 'platform']),
|
75
|
+
placeholderPattern: false,
|
76
|
+
});
|
77
|
+
const appConfigTemplate = (0, template_1.default)(`import __appConfig from 'file';
|
78
|
+
const __appConfigData = __appConfig.platform || __appConfig || {};
|
79
|
+
`, {
|
80
|
+
syntacticPlaceholders: false,
|
81
|
+
placeholderWhitelist: new Set(['file', 'platform']),
|
82
|
+
placeholderPattern: false,
|
83
|
+
});
|
84
|
+
function insertPageConfig(program, filename) {
|
85
|
+
const pageDir = P.dirname(filename);
|
86
|
+
const importBasename = P.basename(filename, P.extname(filename));
|
87
|
+
const pageConfigPath = (0, shared_1.searchJSFile)(`${importBasename}.config`, {
|
88
|
+
cwd: pageDir,
|
89
|
+
});
|
90
|
+
if (fs_1.default.existsSync(pageConfigPath)) {
|
91
|
+
const file = (0, shared_1.replaceExtension)(`./${P.relative(pageDir, pageConfigPath)}`);
|
92
|
+
const ast = pageConfigTemplate({
|
93
|
+
file: t.stringLiteral(file),
|
94
|
+
platform: t.identifier(process.env.PLATFORM),
|
95
|
+
});
|
96
|
+
program.unshiftContainer('body', ast);
|
97
|
+
}
|
98
|
+
else {
|
99
|
+
program.unshiftContainer('body', t.variableDeclaration('const', [
|
100
|
+
t.variableDeclarator(t.identifier('__pageConfigData'), t.objectExpression([])),
|
101
|
+
]));
|
102
|
+
}
|
103
|
+
return true;
|
104
|
+
}
|
105
|
+
function insertAppConfig(program, filename) {
|
106
|
+
const pageDir = P.dirname(filename);
|
107
|
+
const sourceDir = P.join(Builder_1.builder.options.cwd, Builder_1.builder.options.source);
|
108
|
+
const appConfigPath = (0, shared_1.searchJSFile)('app.config', {
|
109
|
+
cwd: sourceDir,
|
110
|
+
});
|
111
|
+
if (fs_1.default.existsSync(appConfigPath)) {
|
112
|
+
const file = (0, shared_1.replaceExtension)(P.relative(pageDir, appConfigPath));
|
113
|
+
const ast = appConfigTemplate({
|
114
|
+
file: t.stringLiteral(file),
|
115
|
+
platform: t.identifier(process.env.PLATFORM),
|
116
|
+
});
|
117
|
+
program.unshiftContainer('body', ast);
|
118
|
+
}
|
119
|
+
else {
|
120
|
+
program.unshiftContainer('body', t.variableDeclaration('const', [
|
121
|
+
t.variableDeclarator(t.identifier('__appConfigData'), t.objectExpression([])),
|
122
|
+
]));
|
123
|
+
}
|
124
|
+
return true;
|
125
|
+
}
|
126
|
+
let appConfig = null;
|
127
|
+
function getAppConfig() {
|
128
|
+
if (appConfig)
|
129
|
+
return appConfig;
|
130
|
+
const sourceDir = P.join(Builder_1.builder.options.cwd, Builder_1.builder.options.source);
|
131
|
+
const appConfigPath = (0, shared_1.searchJSFile)('app.config', {
|
132
|
+
cwd: sourceDir,
|
133
|
+
});
|
134
|
+
if (fs_1.default.existsSync(appConfigPath)) {
|
135
|
+
appConfig = require(appConfigPath);
|
136
|
+
}
|
137
|
+
return appConfig || { pageWrapper: '' };
|
138
|
+
}
|
139
|
+
const { target } = Builder_1.builder.options;
|
140
|
+
const { [target]: { pageWrapper }, } = getAppConfig();
|
141
|
+
/**
|
142
|
+
* 1. 增加小程序运行时 context appConfig pageConfig 的导入, 并共享到 PageInstanceContext 上
|
143
|
+
* 2. 或增加 withPage 的依赖项
|
144
|
+
* 3. 早于 ray-hooks 执行
|
145
|
+
* @param _ babel
|
146
|
+
* @param options compileOptions
|
147
|
+
* @constructor
|
148
|
+
*/
|
149
|
+
function ContextAndHoc() {
|
150
|
+
let entries = [];
|
151
|
+
let isPage;
|
152
|
+
let exportDefaultDeclarationName;
|
153
|
+
return {
|
154
|
+
pre(state) {
|
155
|
+
exportDefaultDeclarationName = '';
|
156
|
+
entries = Object.keys(Builder_1.builder.entry);
|
157
|
+
const sourceDir = (0, slash_1.default)(P.join(Builder_1.builder.options.cwd, Builder_1.builder.options.source));
|
158
|
+
const filename = (0, slash_1.default)(state.opts.filename);
|
159
|
+
const fileName = P.relative(sourceDir, filename);
|
160
|
+
const fileEntryName = fileName.replace(P.extname(fileName), '');
|
161
|
+
isPage = fileEntryName.toLowerCase() !== 'app' && entries.some((e) => e === fileEntryName);
|
162
|
+
},
|
163
|
+
visitor: {
|
164
|
+
ExportDefaultDeclaration(path, state) {
|
165
|
+
if (!isPage)
|
166
|
+
return;
|
167
|
+
const { node } = path;
|
168
|
+
const program = state.file.path;
|
169
|
+
const importer = state.filename;
|
170
|
+
if (pageWrapper && pageWrapper.length) {
|
171
|
+
insertPageConfig(program, importer);
|
172
|
+
if (typeof pageWrapper === 'string') {
|
173
|
+
insertSpecifierImport(program, ['default as RayPageWrapper'], pageWrapper);
|
174
|
+
}
|
175
|
+
else {
|
176
|
+
let i = 0;
|
177
|
+
pageWrapper.forEach((element) => {
|
178
|
+
insertSpecifierImport(program, [`default as RayPageWrapper${i++}`], element);
|
179
|
+
});
|
180
|
+
}
|
181
|
+
}
|
182
|
+
// 导出的引用是一个 FunctionComponent 才进行运行时包裹
|
183
|
+
let pageName = 'default';
|
184
|
+
if (t.isIdentifier(node.declaration)) {
|
185
|
+
pageName = node.declaration.name;
|
186
|
+
path.remove();
|
187
|
+
}
|
188
|
+
else if (t.isFunctionDeclaration(node.declaration)) {
|
189
|
+
if (node.declaration.id) {
|
190
|
+
pageName = node.declaration.id.name;
|
191
|
+
}
|
192
|
+
else {
|
193
|
+
const [_, n] = importer.split(P.sep).reverse();
|
194
|
+
pageName = path.scope.generateUid((0, change_case_1.pascalCase)(n));
|
195
|
+
}
|
196
|
+
const pageFn = t.functionExpression(t.identifier(pageName), node.declaration.params, node.declaration.body);
|
197
|
+
path.replaceWith(t.variableDeclaration('const', [t.variableDeclarator(t.identifier(pageName), pageFn)]));
|
198
|
+
}
|
199
|
+
else if (t.isClassDeclaration(node.declaration)) {
|
200
|
+
if (node.declaration.id) {
|
201
|
+
pageName = node.declaration.id.name;
|
202
|
+
path.replaceWith(node.declaration);
|
203
|
+
}
|
204
|
+
else {
|
205
|
+
const [_, n] = importer.split(P.sep).reverse();
|
206
|
+
pageName = path.scope.generateUid((0, change_case_1.pascalCase)(n));
|
207
|
+
path.replaceWith(t.classDeclaration(t.identifier(pageName), node.declaration.superClass, node.declaration.body, node.declaration.decorators));
|
208
|
+
}
|
209
|
+
}
|
210
|
+
else {
|
211
|
+
pageName = path.scope.generateUid(pageName);
|
212
|
+
path.replaceWith(t.variableDeclaration('const', [
|
213
|
+
// @ts-ignore
|
214
|
+
t.variableDeclarator(t.identifier(pageName), node.declaration),
|
215
|
+
]));
|
216
|
+
}
|
217
|
+
const id = path.scope.generateUid(pageName);
|
218
|
+
const ast = contextTemplate({
|
219
|
+
id: t.identifier(id),
|
220
|
+
compTag: t.jsxIdentifier(pageName),
|
221
|
+
compName: t.identifier(pageName),
|
222
|
+
});
|
223
|
+
if (pageWrapper && pageWrapper.length) {
|
224
|
+
if (typeof pageWrapper === 'string') {
|
225
|
+
exportDefaultDeclarationName = `RayPageWrapper(${id}, __pageConfigData);`;
|
226
|
+
}
|
227
|
+
else {
|
228
|
+
let ename = id;
|
229
|
+
for (let i = 0; i < pageWrapper.length; i++) {
|
230
|
+
ename = `RayPageWrapper${i}(` + ename + ', __pageConfigData)';
|
231
|
+
}
|
232
|
+
ename += ';';
|
233
|
+
exportDefaultDeclarationName = ename;
|
234
|
+
}
|
235
|
+
}
|
236
|
+
else {
|
237
|
+
exportDefaultDeclarationName = id;
|
238
|
+
}
|
239
|
+
program.pushContainer('body', ast);
|
240
|
+
const rayImportSpecifiers = ['PageInstanceContext', 'PageInstance', 'lifecycle'];
|
241
|
+
['usePageEvent', 'router', 'location'].forEach((key) => {
|
242
|
+
if (!path.scope.hasBinding(key)) {
|
243
|
+
rayImportSpecifiers.push(key);
|
244
|
+
}
|
245
|
+
});
|
246
|
+
insertSpecifierImport(program, rayImportSpecifiers, 'ray');
|
247
|
+
insertSpecifierImport(program, ['forwardRef'], 'react');
|
248
|
+
},
|
249
|
+
},
|
250
|
+
post(state) {
|
251
|
+
const program = state.path;
|
252
|
+
if (exportDefaultDeclarationName) {
|
253
|
+
program.pushContainer('body', t.exportDefaultDeclaration(t.identifier(exportDefaultDeclarationName)));
|
254
|
+
}
|
255
|
+
},
|
256
|
+
};
|
257
|
+
}
|
258
|
+
exports.default = ContextAndHoc;
|
package/lib/build.d.ts
ADDED
package/lib/build.js
ADDED
@@ -0,0 +1,224 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9
|
+
});
|
10
|
+
};
|
11
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
12
|
+
var t = {};
|
13
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
14
|
+
t[p] = s[p];
|
15
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
16
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
17
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
18
|
+
t[p[i]] = s[p[i]];
|
19
|
+
}
|
20
|
+
return t;
|
21
|
+
};
|
22
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
23
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
24
|
+
};
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
26
|
+
const colors_1 = __importDefault(require("colors"));
|
27
|
+
const path_1 = __importDefault(require("path"));
|
28
|
+
const pretty_bytes_1 = __importDefault(require("pretty-bytes"));
|
29
|
+
const webpack_1 = __importDefault(require("webpack"));
|
30
|
+
const shared_1 = require("@ray-js/shared");
|
31
|
+
const build_store_1 = __importDefault(require("@remax/build-store"));
|
32
|
+
const API_1 = __importDefault(require("@remax/cli/lib/API"));
|
33
|
+
const legacyExport_1 = require("@remax/cli/lib/legacyExport");
|
34
|
+
const package_json_1 = __importDefault(require("@remax/cli/package.json"));
|
35
|
+
const Builder_1 = require("./Builder");
|
36
|
+
const AppFrameworkEntry_1 = __importDefault(require("./webpack-plugins/AppFrameworkEntry"));
|
37
|
+
colors_1.default.enable();
|
38
|
+
const LOG_PREFIX = 'builder-mp';
|
39
|
+
function build(options, context) {
|
40
|
+
return __awaiter(this, void 0, void 0, function* () {
|
41
|
+
const { api } = context;
|
42
|
+
const compileOptions = Object.assign({
|
43
|
+
cwd: process.cwd(),
|
44
|
+
source: 'src',
|
45
|
+
mode: 'development',
|
46
|
+
watch: false,
|
47
|
+
target: 'wechat',
|
48
|
+
mini: false,
|
49
|
+
analyze: false,
|
50
|
+
devtools: false,
|
51
|
+
debug: false,
|
52
|
+
output: 'dist',
|
53
|
+
}, options);
|
54
|
+
shared_1.log.verbose(LOG_PREFIX, `compileOptions:`, compileOptions);
|
55
|
+
const { cwd, source, mode, watch, target, mini, analyze, debug, output, devtools } = compileOptions;
|
56
|
+
// 上下文共享 options
|
57
|
+
Builder_1.builder.options = compileOptions;
|
58
|
+
process.env.NODE_ENV = mode;
|
59
|
+
process.env.PLATFORM = target;
|
60
|
+
process.env.TUYA_DEVTOOLS = JSON.stringify(devtools);
|
61
|
+
process.env.REMAX_PLATFORM = target; // remax-one 依赖此环境变量
|
62
|
+
if (debug) {
|
63
|
+
process.env.REMAX_DEBUG = 'true'; // remax 运行时日志
|
64
|
+
}
|
65
|
+
const outputPath = (0, shared_1.resolvePath)([output, target], { cwd });
|
66
|
+
shared_1.log.info(LOG_PREFIX, '@remax/cli:'.green, `v${package_json_1.default.version}`);
|
67
|
+
shared_1.log.info(LOG_PREFIX, 'cwd:'.green, cwd.underline);
|
68
|
+
shared_1.log.info(LOG_PREFIX, 'outputDir:'.green, outputPath.underline);
|
69
|
+
devtools &&
|
70
|
+
shared_1.log.info(LOG_PREFIX, '开启 devtools 开发者工具环境变量'.yellow, 'process.evn.TUYA_DEVTOOLS');
|
71
|
+
const _a = (0, legacyExport_1.getDefaultOptions)(), { UNSAFE_wechatTemplateDepth } = _a, remaxDefaultOptions = __rest(_a, ["UNSAFE_wechatTemplateDepth"]);
|
72
|
+
const remaxBuildConfig = Object.assign(Object.assign({}, remaxDefaultOptions), { UNSAFE_wechatTemplateDepth: Object.assign(UNSAFE_wechatTemplateDepth, {
|
73
|
+
swiper: 3,
|
74
|
+
text: 1,
|
75
|
+
ad: -1,
|
76
|
+
'match-media': -1,
|
77
|
+
'page-container': -1,
|
78
|
+
'share-element': -1,
|
79
|
+
'keyboard-accessory': -1,
|
80
|
+
'voip-room': -1,
|
81
|
+
'ad-custom': -1,
|
82
|
+
'page-meta': -1,
|
83
|
+
'navigation-bar': -1,
|
84
|
+
}), compressTemplate: mini, pxToRpx: false, minimize: mini, analyze,
|
85
|
+
cwd, loglevel: 'warn', rootDir: source,
|
86
|
+
// @ts-ignore
|
87
|
+
target: target, output: path_1.default.relative(cwd, outputPath), watch,
|
88
|
+
configWebpack(context) {
|
89
|
+
const { config, addCSSRule } = context;
|
90
|
+
// config.optimization.clear();
|
91
|
+
addCSSRule({
|
92
|
+
name: 'less',
|
93
|
+
test: /\.less(\?.*)?$/,
|
94
|
+
loader: require.resolve('less-loader'),
|
95
|
+
options: {},
|
96
|
+
});
|
97
|
+
const appFile = api.searchJSFile('src/app');
|
98
|
+
shared_1.log.verbose('appFile', appFile);
|
99
|
+
config.plugin('app-framework-entry').use(AppFrameworkEntry_1.default, [appFile]);
|
100
|
+
// 删除 clean-webpack-plugin 插件
|
101
|
+
config.plugins.delete('clean-webpack-plugin');
|
102
|
+
// 修改 mini-css-extract-plugin 的配置
|
103
|
+
config.plugin('mini-css-extract-plugin').tap(([options]) => {
|
104
|
+
return [Object.assign(Object.assign({}, options), { ignoreOrder: true })];
|
105
|
+
});
|
106
|
+
// 收敛 babel.config 配置
|
107
|
+
// 调整 remax 的 babel 配置
|
108
|
+
const babelConfigFile = path_1.default.resolve(__dirname, './configs/babel.config.js');
|
109
|
+
config.module
|
110
|
+
.rule('js')
|
111
|
+
// 此次使用的 loader 是走了 remax 自定义的 babel
|
112
|
+
// @see https://github.com/remaxjs/remax/blob/87d114dc33690c09202054a2fa3fc9b770455935/packages/remax-cli/src/build/webpack/config.mini.ts#L122
|
113
|
+
.use('babel')
|
114
|
+
.tap((options) => {
|
115
|
+
return Object.assign(Object.assign({}, options), { configFile: babelConfigFile });
|
116
|
+
})
|
117
|
+
.end();
|
118
|
+
// 替换 usePageEvent useAppEvent hooks api 模块名
|
119
|
+
config.module
|
120
|
+
.rule('ray-hooks')
|
121
|
+
.test(/\.(js|ts)x?$/)
|
122
|
+
.exclude.add(/node_modules\/(react|react-reconciler|react-dom)/)
|
123
|
+
.end()
|
124
|
+
.pre()
|
125
|
+
.use('hooks-loader')
|
126
|
+
.loader(require.resolve('babel-loader'))
|
127
|
+
.options({
|
128
|
+
babelrc: false,
|
129
|
+
presets: ['@babel/preset-typescript'],
|
130
|
+
plugins: [
|
131
|
+
[require.resolve('./babel-plugins/ray-hooks/index')],
|
132
|
+
'@babel/plugin-syntax-jsx',
|
133
|
+
],
|
134
|
+
})
|
135
|
+
.end()
|
136
|
+
.use('env-loader')
|
137
|
+
.loader(require.resolve('@ray-js/env-loader'))
|
138
|
+
.options({ platform: target })
|
139
|
+
.end();
|
140
|
+
// 对项目下的文件进行 context 实例的包裹
|
141
|
+
// 透传如 pageConfig appConfig
|
142
|
+
config.module
|
143
|
+
.rule('ray-context')
|
144
|
+
.test(/\.(js|ts)x?$/)
|
145
|
+
.include.add(path_1.default.join(Builder_1.builder.options.cwd, Builder_1.builder.options.source))
|
146
|
+
.end()
|
147
|
+
.pre()
|
148
|
+
.use('context-loader')
|
149
|
+
.loader(require.resolve('babel-loader'))
|
150
|
+
.options({
|
151
|
+
babelrc: false,
|
152
|
+
presets: ['@babel/preset-typescript'],
|
153
|
+
plugins: [
|
154
|
+
[require.resolve('./babel-plugins/ray-page-context/index'), Builder_1.builder.options],
|
155
|
+
'@babel/plugin-syntax-jsx',
|
156
|
+
[
|
157
|
+
'@babel/plugin-proposal-decorators',
|
158
|
+
{
|
159
|
+
legacy: true,
|
160
|
+
},
|
161
|
+
],
|
162
|
+
],
|
163
|
+
})
|
164
|
+
.end();
|
165
|
+
config.plugin('defined').use(webpack_1.default.DefinePlugin, [
|
166
|
+
{
|
167
|
+
'process.env.NODE_ENV': JSON.stringify(mode),
|
168
|
+
'process.env.PLATFORM': JSON.stringify(target),
|
169
|
+
'process.env.REMAX_PLATFORM': JSON.stringify(target),
|
170
|
+
},
|
171
|
+
]);
|
172
|
+
config.resolve.alias.set('remax', path_1.default.dirname(require.resolve('remax/package.json')));
|
173
|
+
config.resolve.alias.set('@remax/runtime', path_1.default.dirname(require.resolve('@remax/runtime/package.json')));
|
174
|
+
config.resolve.alias.set('react', path_1.default.dirname(require.resolve('react/package.json')));
|
175
|
+
config.resolve.alias.set('@ray-js/router', '@ray-js/router-mp');
|
176
|
+
config.resolve.alias.set('@ray-js/framework', '@ray-js/framework-mp');
|
177
|
+
// @remax/plugin-error-screen 使用到的 @remax one
|
178
|
+
config.resolve.alias.set('@remax/one', path_1.default.dirname(require.resolve('@ray-js/components/package.json')));
|
179
|
+
api.configIntoWebpackConfig(config);
|
180
|
+
api.callPluginMethod('configWebpack', { config });
|
181
|
+
Builder_1.builder.entry = config.toConfig().entry;
|
182
|
+
} });
|
183
|
+
const remaxApi = new API_1.default();
|
184
|
+
const originalRemax = remaxApi.registerAdapterPlugins;
|
185
|
+
// FIXME: remax 支持注册其他平台适配器
|
186
|
+
remaxApi.registerAdapterPlugins = function (target) {
|
187
|
+
// @ts-ignore
|
188
|
+
if (target === 'tuya') {
|
189
|
+
this.adapter.target = target;
|
190
|
+
this.adapter.packageName = '@ray-js/remax-tuya';
|
191
|
+
const packagePath = this.adapter.packageName + '/node';
|
192
|
+
let plugin = require(packagePath).default || require(packagePath);
|
193
|
+
plugin = typeof plugin === 'function' ? plugin() : plugin;
|
194
|
+
build_store_1.default.skipHostComponents = plugin.skipHostComponents;
|
195
|
+
// @ts-ignore
|
196
|
+
this.registerHostComponents(plugin.hostComponents);
|
197
|
+
this.plugins.push(plugin);
|
198
|
+
}
|
199
|
+
else {
|
200
|
+
originalRemax.call(this, target);
|
201
|
+
}
|
202
|
+
};
|
203
|
+
const compiler = (0, legacyExport_1.buildMini)(remaxApi, Object.assign({}, remaxBuildConfig));
|
204
|
+
compiler.hooks.done.tap('tuya-scripts', (stats) => {
|
205
|
+
var _a;
|
206
|
+
const json = stats.toJson();
|
207
|
+
const size = (_a = json.assets) === null || _a === void 0 ? void 0 : _a.reduce((acc, asset) => {
|
208
|
+
return acc + asset.size;
|
209
|
+
}, 0);
|
210
|
+
console.log(stats.toString({
|
211
|
+
colors: true,
|
212
|
+
entrypoints: false,
|
213
|
+
assets: watch ? false : true,
|
214
|
+
children: false,
|
215
|
+
modules: false,
|
216
|
+
}));
|
217
|
+
console.log('');
|
218
|
+
shared_1.log.info(LOG_PREFIX, `Output size ${size} bytes`.yellow, (0, pretty_bytes_1.default)(size).bgMagenta.white);
|
219
|
+
console.log('');
|
220
|
+
});
|
221
|
+
return compiler;
|
222
|
+
});
|
223
|
+
}
|
224
|
+
exports.default = build;
|
@@ -0,0 +1,18 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
function babelConfig(api) {
|
4
|
+
api.cache(true);
|
5
|
+
return {
|
6
|
+
presets: [
|
7
|
+
[
|
8
|
+
require.resolve('babel-preset-remax'),
|
9
|
+
{ typescript: true, decorators: { legacy: true }, classProperties: { loose: true } },
|
10
|
+
],
|
11
|
+
],
|
12
|
+
plugins: [
|
13
|
+
require.resolve('babel-plugin-minify-dead-code-elimination'),
|
14
|
+
require.resolve('babel-plugin-transform-prune-unused-imports'),
|
15
|
+
],
|
16
|
+
};
|
17
|
+
}
|
18
|
+
exports.default = babelConfig;
|
package/lib/index.d.ts
ADDED
package/lib/index.js
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.build = void 0;
|
7
|
+
const build_1 = __importDefault(require("./build"));
|
8
|
+
exports.build = build_1.default;
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import VirtualModules from 'webpack-virtual-modules';
|
2
|
+
import { Compiler } from 'webpack';
|
3
|
+
/**
|
4
|
+
* 小程序框架启动, 在文件顶部增加 .ray/main.mini 的适配
|
5
|
+
* 读取 TabBar 信息,注册页面到 router 上。实现 web 路由的跳转
|
6
|
+
*/
|
7
|
+
export default class AppFrameworkEntry {
|
8
|
+
virtualModules: VirtualModules;
|
9
|
+
source: string;
|
10
|
+
appFile: string;
|
11
|
+
constructor(appFile: string);
|
12
|
+
apply(compiler: Compiler): void;
|
13
|
+
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9
|
+
});
|
10
|
+
};
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
13
|
+
};
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
15
|
+
const webpack_virtual_modules_1 = __importDefault(require("webpack-virtual-modules"));
|
16
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
17
|
+
const PLUGIN_NAME = `AppFrameworkEntry`;
|
18
|
+
const AppFrameworkTemplate = function (source) {
|
19
|
+
return `import 'ray/main';
|
20
|
+
${source}`;
|
21
|
+
};
|
22
|
+
/**
|
23
|
+
* 小程序框架启动, 在文件顶部增加 .ray/main.mini 的适配
|
24
|
+
* 读取 TabBar 信息,注册页面到 router 上。实现 web 路由的跳转
|
25
|
+
*/
|
26
|
+
class AppFrameworkEntry {
|
27
|
+
constructor(appFile) {
|
28
|
+
this.virtualModules = new webpack_virtual_modules_1.default();
|
29
|
+
this.source = ``;
|
30
|
+
this.appFile = appFile;
|
31
|
+
}
|
32
|
+
apply(compiler) {
|
33
|
+
const { context } = compiler.options;
|
34
|
+
compiler.hooks.make.tapAsync(PLUGIN_NAME, (compilation, callback) => __awaiter(this, void 0, void 0, function* () {
|
35
|
+
this.virtualModules.apply(compiler);
|
36
|
+
const appSource = yield fs_extra_1.default.readFile(this.appFile).then((b) => b.toString());
|
37
|
+
const newSource = appSource;
|
38
|
+
if (newSource !== this.source) {
|
39
|
+
this.source = newSource;
|
40
|
+
this.virtualModules.writeModule(this.appFile, AppFrameworkTemplate(this.source));
|
41
|
+
}
|
42
|
+
callback();
|
43
|
+
}));
|
44
|
+
compiler.hooks.afterCompile.tap(PLUGIN_NAME, (compilation) => {
|
45
|
+
compilation.fileDependencies.add(this.appFile);
|
46
|
+
});
|
47
|
+
}
|
48
|
+
}
|
49
|
+
exports.default = AppFrameworkEntry;
|
package/package.json
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
{
|
2
|
+
"name": "@ray-js/builder-mp",
|
3
|
+
"version": "0.3.0-beta.1c347991",
|
4
|
+
"description": "Ray builder for mini program",
|
5
|
+
"keywords": [
|
6
|
+
"ray"
|
7
|
+
],
|
8
|
+
"author": "子长 <zichang.nong@tuya.com>",
|
9
|
+
"license": "MIT",
|
10
|
+
"main": "lib/index.js",
|
11
|
+
"files": [
|
12
|
+
"lib"
|
13
|
+
],
|
14
|
+
"publishConfig": {
|
15
|
+
"access": "public",
|
16
|
+
"registry": "https://registry.npmjs.org"
|
17
|
+
},
|
18
|
+
"scripts": {
|
19
|
+
"clean": "rm -rf lib",
|
20
|
+
"build": "tsc -p ./tsconfig.build.json",
|
21
|
+
"watch": "tsc -p ./tsconfig.build.json --watch",
|
22
|
+
"test": "jest"
|
23
|
+
},
|
24
|
+
"dependencies": {
|
25
|
+
"@babel/template": "^7.16.0",
|
26
|
+
"@babel/traverse": "^7.16.3",
|
27
|
+
"@babel/types": "^7.16.0",
|
28
|
+
"@ray-js/remax-tuya": "^0.3.0-beta.1c347991",
|
29
|
+
"@ray-js/shared": "^0.3.0-beta.1c347991",
|
30
|
+
"@ray-js/types": "^0.3.0-beta.1c347991",
|
31
|
+
"@remax/build-store": "2.15.6",
|
32
|
+
"@remax/cli": "2.15.6",
|
33
|
+
"@remax/plugin-less": "^1.0.0",
|
34
|
+
"@remax/types": "2.15.6",
|
35
|
+
"babel-loader": "^8.2.3",
|
36
|
+
"babel-plugin-minify-dead-code-elimination": "^0.5.1",
|
37
|
+
"babel-plugin-transform-prune-unused-imports": "^1.0.1",
|
38
|
+
"babel-preset-remax": "2.15.6",
|
39
|
+
"change-case": "^4.1.2",
|
40
|
+
"colors": "1.4.0",
|
41
|
+
"fs-extra": "^10.0.0",
|
42
|
+
"less": "3.x",
|
43
|
+
"postcss-units-transform": "^1.1.0",
|
44
|
+
"pretty-bytes": "^5.6.0",
|
45
|
+
"react": "^17.0.2",
|
46
|
+
"remax": "2.15.6",
|
47
|
+
"rimraf": "^3.0.2",
|
48
|
+
"slash": "^3.0.0",
|
49
|
+
"webpack": "^4",
|
50
|
+
"webpack-chain": "^6.5.1",
|
51
|
+
"webpack-virtual-modules": "^0.4.3"
|
52
|
+
},
|
53
|
+
"devDependencies": {
|
54
|
+
"@types/jest": "^27.0.2",
|
55
|
+
"@types/node": "^16.9.1",
|
56
|
+
"babel-plugin-tester": "^10.1.0",
|
57
|
+
"jest": "^27.2.2",
|
58
|
+
"ts-jest": "^27.0.5",
|
59
|
+
"typescript": "^4.4.3"
|
60
|
+
},
|
61
|
+
"maintainers": [
|
62
|
+
{
|
63
|
+
"name": "tuyafe",
|
64
|
+
"email": "tuyafe@tuya.com"
|
65
|
+
}
|
66
|
+
],
|
67
|
+
"gitHead": "e0bd013022ddda63380d3c9e20fd8cadb46cd61f",
|
68
|
+
"repository": {}
|
69
|
+
}
|