@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.
Files changed (25) hide show
  1. package/lib/Builder.d.ts +11 -0
  2. package/lib/Builder.js +22 -0
  3. package/lib/babel-plugins/ray-hooks/index.d.ts +14 -0
  4. package/lib/babel-plugins/ray-hooks/index.js +63 -0
  5. package/lib/babel-plugins/ray-page-context/__fixtures__/page-anonymous-fn/code.config.d.ts +3 -0
  6. package/lib/babel-plugins/ray-page-context/__fixtures__/page-anonymous-fn/code.config.js +6 -0
  7. package/lib/babel-plugins/ray-page-context/__fixtures__/page-fn/code.config.d.ts +3 -0
  8. package/lib/babel-plugins/ray-page-context/__fixtures__/page-fn/code.config.js +6 -0
  9. package/lib/babel-plugins/ray-page-context/__fixtures__/page-instance/code.config.d.ts +3 -0
  10. package/lib/babel-plugins/ray-page-context/__fixtures__/page-instance/code.config.js +6 -0
  11. package/lib/babel-plugins/ray-page-context/__fixtures__/single/code.config.d.ts +3 -0
  12. package/lib/babel-plugins/ray-page-context/__fixtures__/single/code.config.js +6 -0
  13. package/lib/babel-plugins/ray-page-context/app.config.d.ts +3 -0
  14. package/lib/babel-plugins/ray-page-context/app.config.js +6 -0
  15. package/lib/babel-plugins/ray-page-context/index.d.ts +17 -0
  16. package/lib/babel-plugins/ray-page-context/index.js +258 -0
  17. package/lib/build.d.ts +5 -0
  18. package/lib/build.js +224 -0
  19. package/lib/configs/babel.config.d.ts +12 -0
  20. package/lib/configs/babel.config.js +18 -0
  21. package/lib/index.d.ts +2 -0
  22. package/lib/index.js +8 -0
  23. package/lib/webpack-plugins/AppFrameworkEntry/index.d.ts +13 -0
  24. package/lib/webpack-plugins/AppFrameworkEntry/index.js +49 -0
  25. package/package.json +69 -0
@@ -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,3 @@
1
+ export declare const wechat: {
2
+ a: number;
3
+ };
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.wechat = void 0;
4
+ exports.wechat = {
5
+ a: 1,
6
+ };
@@ -0,0 +1,3 @@
1
+ export declare const wechat: {
2
+ a: number;
3
+ };
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.wechat = void 0;
4
+ exports.wechat = {
5
+ a: 1,
6
+ };
@@ -0,0 +1,3 @@
1
+ export declare const wechat: {
2
+ a: number;
3
+ };
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.wechat = void 0;
4
+ exports.wechat = {
5
+ a: 1,
6
+ };
@@ -0,0 +1,3 @@
1
+ export declare const wechat: {
2
+ config: number;
3
+ };
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.wechat = void 0;
4
+ exports.wechat = {
5
+ config: 1,
6
+ };
@@ -0,0 +1,3 @@
1
+ export declare const wechat: {
2
+ app: number;
3
+ };
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.wechat = void 0;
4
+ exports.wechat = {
5
+ app: 1,
6
+ };
@@ -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
@@ -0,0 +1,5 @@
1
+ import webpack from 'webpack';
2
+ import { API, CliOptions } from '@ray-js/types';
3
+ export default function build(options: CliOptions, context: {
4
+ api: API;
5
+ }): Promise<webpack.Compiler>;
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,12 @@
1
+ export default function babelConfig(api: any): {
2
+ presets: (string | {
3
+ typescript: boolean;
4
+ decorators: {
5
+ legacy: boolean;
6
+ };
7
+ classProperties: {
8
+ loose: boolean;
9
+ };
10
+ })[][];
11
+ plugins: string[];
12
+ };
@@ -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
@@ -0,0 +1,2 @@
1
+ import build from './build';
2
+ export { build };
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
+ }