This topic describes the step-by-step process of developing frontend micro applications.
After you run npx @tuya-sat/create-micro-app@latest demo -t react-ts
in a command-line tool, a react-ts
template is created. react-ts
template is recommended because some features are compatible with the react
only. ts
is adopted for efficient code maintenance. The directory of the demo
folder is as follows:
.├── README.md├── _locales // manifest.json Multilingual UI text.│ ├── en.json│ └── zh-CN.json├── antd.less.overwrite.js // Used to edit the Less variable related to theme color. Both dark and light themes are supported.├── babel.config.json // The configuration file of `babel-import-plugin`, allowing you to load external CSS files as needed.├── manifest.json // Declaration of the micro application. See manifest for details.├── micro.config.js // The configuration file of Webpack and webpack-dev-server as well as the data for debugging.├── mock // Files for the Mock feature.│ └── index.json├── package.json // Includes plugins and plugin set. Dependency prefixed with @tuya-sat will be installed and registered automatically.├── public // The public file.│ ├── favicon.ico│ └── index.html├── src│ ├── App.css│ ├── App.tsx│ ├── api // An Axios library used to make requests.│ │ ├── index.ts│ │ ├── req.ts│ │ └── res.ts│ ├── assets // URLs of assets such as images and fonts.│ │ └── logo.png│ ├── components│ │ ├── HelloTemplate│ │ │ ├── index.module.less│ │ │ └── index.tsx│ │ ├── ModalForm│ │ │ └── index.tsx│ │ ├── Table│ │ │ ├── index.module.less│ │ │ └── index.tsx│ │ └── Theme│ │ ├── index.module.less│ │ └── index.tsx│ ├── index.css│ ├── index.tsx // The entry file.│ ├── lang // The multilingual UI text for micro applications.│ │ ├── en.ts│ │ ├── index.ts│ │ └── zh.ts│ ├── pages // The page components.│ │ ├── index.module.less│ │ └── index.tsx│ ├── public-path.js // Injects Qiankun-related variables.│ └── styles // Files for theme colors.│ ├── dark.less│ ├── global.less│ └── light.less├── tsconfig.json└── typings.d.ts
Open micro.config.js
.
/** @typedef {import("@tuya-sat/micro-script").DebuggerConfig} DebuggerConfig *//** @typedef {import("@tuya-sat/micro-script").WebpackCombineFunction} WebpackCombineFunction *//** @typedef {import("@tuya-sat/micro-script").CustomDevServer} CustomDevServer */module.exports = {/**@type {DebuggerConfig} */debuggerConfig: {target: 'xxx', // Proxy protocol+host are required.username: 'xxxx', // The admin account of the created SaaS.password: 'xxx', // The password of the admin account.logSign: true, // Print the request header.mockPermissions: ['EDIT', 'DELETE'],},/**@type {WebpackCombineFunction} */webpack(config, { isDev, isBuild }) {config.output.publicPath = isDev ? '/' : './';return config;},/**@type {CustomDevServer} */devServer(config) {return config;},};
debuggerConfig
is used to configure the debugging information. Set target
to the URL of the SaaS you have just created. The protocol and host must be entered.
For simplicity, we only show the code you should take care of.
/** @typedef {import("@tuya-sat/micro-script").DebuggerConfig} DebuggerConfig *//** @typedef {import("@tuya-sat/micro-script").WebpackCombineFunction} WebpackCombineFunction *//** @typedef {import("@tuya-sat/micro-script").CustomDevServer} CustomDevServer */module.exports = {/**@type {DebuggerConfig} */debuggerConfig: {target: 'Enter the URL of the created SaaS', // Proxy protocol+host are required.},};
Run the following command in the project directory:
yarn start
The following figure shows a demo page. In your project, you can delete unwanted components
.
The system automatically creates a file .sass-cache.json
in the project root directory. This is a cache file for the SaaS configuration. If you encounter unexpected problems during debugging, you can try deleting this file and starting up the service again.
As the documentation says, a micro application should declare all the APIs it uses.
Now, a project has been started. With the mock rules, requests are sent from the client to the server and are correctly responded to. Open mock/index.json
.
{"mock": true,"api": [{"path": "/open-api/v1.0/users","method": "GET","res": {"msg": "","success": true,"result": {"data": [{"create_time": "1637204610430","roles": [{"remark": "","role_code": "admin","role_name": "admin"}],"user_id": "bay1637204610495B***","user_name": "admin","user_nick_name": "Admin"},{"create_time": "1637741963865","roles": [{"remark": "","role_code": "test","role_name": "test"}],"user_id": "bay16372041489899***","user_name": "test","user_nick_name": "Admin"}]}},"mock": true},{"path": "/open-api/v1.0/users","method": "DELETE","res": {"msg": "","success": true,"data": {}},"mock": true},{"path": "/open-api/v1.0/users","method": "PUT","res": {"msg": "","success": true,"data": {}},"mock": true}]}
The outermost json
object has a mock
field:
{"mock": true,"api": [...]}
The mock
field is used to enable mock for APIs in all api
arrays. It acts as a global on/off switch for the mock feature. If mock
is set to false
, all APIs in the api
arrays are not mocked, but not vice-versa.
In an api
array, each API has its own mock setting:
{"mock": true,"api": [{"path": "/open-api/v1.0/users","method": "PUT","res": {"msg": "","success": true,"data": {}},"mock": true // Check out here.}]}
To mock this API, this mock
field must be set to true
. If it is set to false
, even if the outermost mock
is set to true
, the mock feature will not work.
INFO
Changes made to mock/index.json
take effect immediately, without the service being restarted.
For more information about mock configuration, see Permissions Mock.
As the documentation says, each micro application can declare its permissions. Permissions are associated with APIs.
For more information about the manifest configuration, see Description Protocol.
Open manifest.json
.
{"type": "micro-apps/v1.1","appName": "demo","supportedPlatform": ["DESKTOP"],"annotations": {"sdf.cli:microFramework": "REACT_JS","sdf.feat:colorTheme": true},"universalId": "42350097-d1bd-441f-b174-21e10afe7***","appEngine": "MICRO-FRONTEND","name": "lang.name","defaultMenuIcon": {"type": "tuyaIcon","name": "sat_factory_modeling"},"description": "lang.description","entries": [],"configs": [],"privileges": [{"name": "lang.edit","code": "EDIT"},{"name": "lang.delete","code": "DELETE"}],"apis": [{"namespace": "","method": "GET","path": "/v1.0/users","privilegeCode": "","type": "OpenAPI"},{"namespace": "","method": "PUT","path": "/v1.0/users","privilegeCode": "EDIT","type": "OpenAPI"},{"namespace": "","method": "DELETE","path": "/v1.0/users","privilegeCode": "DELETE","type": "OpenAPI"}],"dependencies": []}
This is a complete manifest.json
file. Check out the privileges
field:
{"privileges": [{"name": "lang.edit","code": "EDIT"},{"name": "lang.delete","code": "DELETE"}] // Check out here.}
privileges
is an array, with each element containing the name
and code
properties. code
is the key value of a privilege.
In some use cases, UI rendering depends on the privilege. For example, the Delete
button rendering varies depending on the role of the user. For users granted the DELETE
privilege, the button is active, while for users not granted the DELETE
privilege, the button is grayed out. We need to mock the button behaviors locally. In the demo, the Delete
button is active.
Let's see how this is implemented. The following code is from the file micro.config.js
:
module.exports = {/**@type {DebuggerConfig} */debuggerConfig: {mockPermissions: ['EDIT', 'DELETE'], // Check out here.},};
mockPermissions
in debuggerConfig
is an array of privilege
codes. The above code indicates that the user that is accessing this micro application has the EDIT
and DELETE
privileges. Assume that this user does not have the DELETE
privilege. You can delete the DELETE
string from mockPermissions
. After the code is edited:
module.exports = {/**@type {DebuggerConfig} */debuggerConfig: {mockPermissions: ['EDIT'], // Check out here.},};
Refresh the page. The Delete
button is greyed out.
Let's see how this is implemented. Open src/components/Table/index.tsx
and go to line 92
.
<Buttontype="link"disabled={!hasPermission!('DELETE')} // Check out here.onClick={() => deleteUsers(record.user_id)}>{t('table.delete')}</Button>
The status of the Button
component depends on the result returned by the function hasPermission!('DELETE')
. hasPermission
is an API exposed by the main application. The request parameter is the value of the code
we delete from mockPermissions
. mockPermissions
does not contain this value, so hasPermission!('DELETE')
returns false
.
When you develop micro applications locally, the function hasPermission
can be used as follows:
function hasPermission(code) {return mockPermissions.includes(code);}
In actual use, this function does not look like this.
In actual use, the backend API will check the user login status, so we need to simulate the login behavior. We need to edit micro.config.js
to configure the username and password.
module.exports = {/**@type {DebuggerConfig} */debuggerConfig: {target: 'Enter the URL of the created SaaS', // Proxy protocol+host are required.username: 'xxxx', // The admin account of the created SaaS.password: 'xxx', // The password of the admin account.logSign: true, // Print the request header.mockPermissions: ['EDIT', 'DELETE'],},};
username
and password
have not been configured. Configure them to the admin account and password you set for the created SaaS.
module.exports = {/**@type {DebuggerConfig} */debuggerConfig: {target: 'Enter the URL of the created SaaS', // Proxy protocol+host are required.username: 'Admin Account', // The admin account of the created SaaS.password: 'Password', // The password of the admin account.logSign: true, // Print the request header.mockPermissions: ['EDIT', 'DELETE'],},};
Exit the service and run the following command to restart the service.
yarn start:proxy
Then, you can debug APIs. The command-line tool will output the header of the request via a proxy.
CAUTION
mock/index.json
is still valid. If the API you are debugging is located in this file, set the mock
of this API to false
or set the global mock
to false
.open-api
or custom-api
. Check whether the response in src/api/res.ts
is as expected.This is a simple process to develop a micro application.