您是否已经厌倦了将应用程序发送到Apple或Google每次更新时对其进行审查?
在这里我提供了可能的解决方案。解决方案是因为您可以绕过90%的时间甚至更多。
您可能知道,我们有4种构建移动应用程序的方法:
- 本机 - iOS的一个应用程序,一个用于Android的应用程序,
- 编译 - 一个代码库编译为用React Native或Flutter编写的2个本机应用程序,例如
- Hybrid- Web应用程序在移动应用程序内部的Web视图中打开 - 我们构建Web应用程序,然后使用Capacitor例如在本机移动应用程序中运行此Web应用程序,
- PWA-基本上是一个网络应用程序,托管在网络上,但表现得像移动应用程序(处理离线模式等)。
在本文中,我想展示我们如何使用第三种方法来制作移动应用程序,该应用只需上传到App Store和Google Play,然后就不需要应用程序进行评论一次它在更新时不再了。
当我们更新此类应用程序时,我们可以将新代码部署到任何服务器,云,静态站点托管提供商或任何适合Web应用程序的地方,而不是:
- 构建整个应用程序,
- 将其上传到App Store和Google Play,
- 然后等待新版本的批准。
让我们看看如何完成!
让我们从一些理论开始
我提到,在混合移动应用程序的情况下,我们手头有Capacitor。
说实话,我们不仅有电容器,而且还有Cordova哪个电容器所基于的,而且由于电容器更受欢迎,社区更好,更好地解决了一些问题,并且与Ionic Framework合作,我将在第二秒内告诉更多,我将在第二秒内告诉更多问题我只推荐电容器。
和顺便说一句。人们喜欢科尔多瓦(Cordova)像The State of JS 2022或同年的StackOverflow Survey,建议推荐电容器而不是科尔多瓦(Cordova)看起来很合理:
电容器是一个运行时环境,我们可以用它来打开移动本机应用程序内部的Web应用程序。
此外,它还提供了我们可以用来处理本地功能的插件,例如:
- 地理位置,
- sharing,
- 通知,
- 加速度计,
- 和许多其他。
有一个很好的草图说明了我从文章中获得的电容器的工作方式:“CapacitorJS: Turn Your Web App into a Mobile App”:
这对我们意味着什么?
这意味着要使用电容器制作移动应用程序,我们不需要了解如何创建Web应用程序!
处理天然功能的处理归结为使用简单的JavaScript API。例如:
import { Geolocation } from '@capacitor/geolocation';
const printCurrentPosition = async () => {
const coordinates = await Geolocation.getCurrentPosition();
console.log('Current position:', coordinates);
};
另外,正如我提到的,我们可以帮助自己使用Ionic-可以基于React,Vue或Angular的框架,并且提供路由,主题,样式,最重要的是 - 许多用于移动组件的内置组件喜欢:
警报:
切换:
还有许多其他:
所有这些都具有针对iOS和Android的专用样式。
回到主要主题 - 如果我们的应用程序只是一个Web应用程序,它可以以与Web应用程序相同的方式使用微观前端!
因此,我们可以创建2个单独的微观前端(MFS):
- 第一个消耗第二MF并且无能为力的MF,
- 和第二个执行其他一切的MF。
然后,第一个MF将由我们构建,并将其上传到App Store和Play商店。
第二个MF将被放置在某些URL之下,例如https://our-awesome-micro-frontend.com
,并由第一个MF在运行时检索(每次用户运行我们的应用程序)。
在这种情况下,要更新我们的移动应用程序,我们不需要构建它并每次上传到App Store和Play商店,而只是更新第二个远程MF并将其部署到服务器。第一个MF将在运行时检索第二个版本的最新版本。
但是,Apple和Google基本上可以忽略他们的审核流程吗?
我问自己同样的问题,答案是 - 他们对此都可以。
以这种方式实施的微观前端被视为从外部API检索的任何其他内容。
足够的理论!让我们通过创建我们的基本应用程序和微观前端来检查它,它将消费
对于我今天将要显示的所有内容的代码,您可以检查我的
[ionic-module-federation
github存储库](https://github.com/robert-orlinski/ionic-module-federation)!
我将使用Ionic脚手架,默认情况下使用电容器(前面提到)。
我将选择反应作为二手框架,但您可以选择Angular或Vue。
如果我选择反应作为二手框架,则Ionic的样板基于Create React App。因此,我想要一个编辑Webpack’s配置的工具,而无需ejecting Cra的配置。
为什么?
所有内容,因为我将使用WebPack的module federation处理我们的微观前端。
如果您不熟悉模块联合会,则可以在YouTube上检查这些视频:
我将使用用于更改我们的WebPack配置的工具是CRACO。
让我们去
我们可以创建一个新的目录(让我们称其为ionic-module-federation
):
mkdir ionic-module-federation
cd ionic-module-federation
内部我们创建了2个新项目:
- 1对于我们的基本应用程序,它将上传到App Store和Google Play,
- 和1用于基本应用程序将消费的微观前端。
要板条,我们可以安装@ionic/cli,然后为两个应用程序运行ionic start
:
npm install -g @ionic/cli
ionic start
然后,我们通过基本应用的向导:
? Use the app creation wizard? No
? Framework: React
? Project name: host
? Starter template: blank
? Create free Ionic account? No
浏览我选择的选项:
- 我不想使用应用程序创建向导。如果这样做的话,我将被重定向到Ionic的网站,需要创建一个帐户,并且我的应用程序将自动添加到Appflow’s帐户中。我不需要这些。
- 我选择反应作为我的JS框架。
-
host
是我的基本应用的名称。 - 我不想要我的基本应用程序的任何入门模板,所以我选择
blank
。 - 我不想像我在第一点提到的Ionic的帐户。
,然后对我们的基本应用程序消耗的微端端执行相同的操作:
? Use the app creation wizard? No
? Framework: React
? Project name: remote
? Starter template: list
? Create free Ionic account? No
这里唯一的区别是:
- 名称(当然)。
- 我正在使用启动模板的事实。在您的情况下可能不是必需的,但是要很好地显示我们的基本应用如何消耗
remote
应用程序,我将使用它。
然后我们与我们的两个前端项目降落
文件结构看起来像这样:
它们两个都基于Create React App。
当然,现在我们可以以离子和电容器的方式开发我们的应用程序,让我们开发它们:
- 创建Web应用程序,
- 使用电容器插件需要在我们需要的地方处理本地功能,
- 为iOS和Android构建我们的应用程序,
- 使用Xcode和Android Studio测试它们,
- 将它们上传到App Store和Google Play。
但是这些动作不是我现在要采取的行动。您可以在Ionic,Capacitor,Apple和Google文档中阅读更多有关它们的信息。
现在,我想做微观前端的事情! ð¥³
因此,让我们为两个应用程序配置模块联合会!
正如我提到的,在我们的情况下,这项工作的理想工具是CRACO。它将让我们简单地覆盖Cra的配置而不会弹出。
开始,我们可以为两个应用程序安装它:
cd host
npm i -D @craco/craco
cd remote
npm i -D @craco/craco
您可以使用npm workspaces或yarn workspaces安装一次。
,然后创建一个将我们的配置放置的文件。文件必须称为craco.config.js
。
我们将为两个应用程序创建它-host
和remote
。
对于host
,我们的craco.config.js
将有这样的内容:
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const deps = require('./package.json').dependencies;
module.exports = {
webpack: {
configure: {
output: {
publicPath: 'auto',
},
},
plugins: {
add: [
new ModuleFederationPlugin({
name: 'host',
remotes: {
remote: 'remote@http://localhost:3002/remoteEntry.js',
},
exposes: {},
filename: 'remoteEntry.js',
shared: {
...deps,
react: {
singleton: true,
eager: true,
requiredVersion: deps['react'],
},
'react-dom': {
singleton: true,
eager: true,
requiredVersion: deps['react-dom'],
},
},
}),
],
},
},
};
其中http://localhost:3002
是我们的remote
应用的地址。
如果您将remote
应用程序上传到某些远程服务器,则需要用服务器的URL替换。
fyi-要始终在port
。。3002
上打开remote
应用程序,而不是默认的3000
i更改remote
的remote
的脚本从react-scripts start
到PORT=3002 react-scripts
。
反过来,对于remote
app craco.config.js
将具有此内容:
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const deps = require('./package.json').dependencies;
module.exports = {
webpack: {
configure: {
output: {
publicPath: 'auto',
},
},
plugins: {
add: [
new ModuleFederationPlugin({
name: 'remote',
remotes: {},
exposes: {
'./App': './src/App',
},
filename: 'remoteEntry.js',
shared: {
...deps,
react: {
singleton: true,
eager: true,
requiredVersion: deps['react'],
},
'react-dom': {
singleton: true,
eager: true,
requiredVersion: deps['react-dom'],
},
},
}),
],
},
},
};
非常相似。唯一的区别是,我们不用在模块联合配置中设置遥控器,而是公开特定的组件。
然后我们可以使用裸露的组件
就我而言,我只暴露了一个组件。这是主要的(App
),因为我想基本上消耗整个remote
应用程序。
然后,要消耗此组件,我们可以以这种方式将其导入host
应用程序中:
import App from 'remote/App';
我将在host/index.tsx
文件中进行。
btw。关于
.tsx
文件 - 默认情况下离子支持打字稿,甚至没有办法用经典JS编写的文件生成样板。
ionic建议,如果由于某种原因不想使用TS,您可以简单地重命名所有文件并从中删除类型注释。
可能您已经发现了当我们导入App
时,您已经发现了Typescript的错误:
这是因为模块联合不包含任何类型。
我现在可以通过例如创建名为remote.d.ts
的文件在我们的src
目录中的文件,并在内部放置代码:
declare module 'remote/App';
但是,当然,这不是一个很好的解决方案。
您可以在我之前提到过几段的5th part of Five Module Federation/Micro-Frontend Mistakes视频中找到更好的解决方案。
现在我们可以运行我们的应用!
但还有一件事。
要使用craco,我们需要更改package.json
文件中的start
,build
和test
命令。
// host:
"scripts": {
"start": "PORT=3002 craco start",
"build": "craco build",
"test": "craco test --transformIgnorePatterns 'node_modules/(?!(@ionic/react|@ionic/react-router|@ionic/core|@stencil/core|ionicons)/)'",
"eject": "react-scripts eject"
},
// remote:
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test --transformIgnorePatterns 'node_modules/(?!(@ionic/react|@ionic/react-router|@ionic/core|@stencil/core|ionicons)/)'",
"eject": "react-scripts eject"
},
然后我们可以运行两个应用程序ð
让我们两次使用npm start
-在host
和remote
应用程序中分别使用:
cd host
npm start
cd remote
npm start
aaaaand让我们在运行时获得此错误:
ouch§
幸运的是,没有什么可担心的。
我们只需要创建新文件(让它调整为src/bootstrap.tsx
),将src/index.tsx
内容复制到其中,然后更改已经复制的src/index.tsx
内容到:
import('./bootstrap');
export {};
您可以在本文中阅读有关该主题的更多信息:Module Federation. Advanced API in Webpack 5.0.0-beta.17
现在我们重新启动应用程序。
我们应该在[localhost:3000](http://localhost:3000/)
(host
)和[localhost:3002](http://localhost:3002/)
(remote
)下看到相同的内容:
这意味着,我们的模块联合会工作! ð¥³
我们可以更改remote/App
组件内部的任何内容,并看到在[localhost:3000](http://localhost:3000/)
和[localhost:3002](http://localhost:3002/)
上可见更改。
这也意味着在将应用程序上传到App Store和Google Play之后,我们将能够跳过移动应用程序的评论!
我们不必编辑host
Micro Frontend内部的任何内容(然后将其上传到App Store和Google Play)才能更新我们的移动应用程序。
我们始终只能更新remote
Micro Frontend(我们可以在Internet上的某个地方托管的相同),然后在运行时检索它。
请注意 - 只要我们不需要在移动应用中添加任何本地功能,我们就可以做到这一点
如果我们要处理remote
中的地理位置,通知或加速度计之类的内容,则必须在host
和remote
中安装适当的电容器插件,然后同步本机应用程序。
我们可以这样做以显示其工作原理。
让测试sharing native functionality。
首先,我们可以在remote
应用中添加一些代码,以处理内容共享。
我将在Home
组件的末端添加非常简单的button
,它将在单击时调用共享:
// ...
<IonList>
{messages.map((m) => (
<MessageListItem key={m.id} message={m} />
))}
</IonList>
</IonContent>
<IonButton
onClick={async () => {
await Share.share({
title: 'See cool stuff',
text: 'Really awesome thing you need to see right meow',
url: 'http://ionicframework.com/',
dialogTitle: 'Share with buddies',
});
}}
>
Share
</IonButton>
</IonPage>
// ...
Share
是从处理共享功能的@capacitor/share
插件导入的:
import { Share } from '@capacitor/share';
当然,必须安装我们的@capacitor/share
插件:
# ...in `host` app to take it into consideration while updating native platforms:
cd host
npm install @capacitor/share
# ...and in `remote` app to import it properly and without errors:
cd remote
npm install @capacitor/share
然后我可以构建我们的host
应用并为本机平台生成它。
出于测试目的,我将仅在我们的离子项目中添加iOS平台,然后在xcode的内部生成并打开我们的应用程序:
cd remote
npm start # If we want to run our `host` app after building it and consume our micro frontend, `remote` app has to operate.
cd host
ionic capacitor add ios
npm run build
ionic capacitor sync --no-build # `ionic capacitor sync` builds our app using `react-scripts` so because I use CRACO, I don't use this default build to happen. I build our app using `npm run build` before running `ionic capacitor sync`.
ionic capacitor open ios
运行ionic capacitor open ios
后,本机应用程序在xcode内部打开。当我们运行它时,我们会在家庭视图的底部看到我们的按钮:
然后,当我们单击它时,我们可以看到我们的共享菜单:
,如果我们仅在remote
应用程序中添加@capacitor/share
软件包,那将不起作用。我们还必须将其添加到我们的主要应用程序中 - 即host
App。
就是这样!
再次,您可以检查
[ionic-module-federation
repo](https://github.com/robert-orlinski/ionic-module-federation)在本教程中创建的代码。
以我显示的方式,我们可以随时部署新版本的新版本:
- 不询问苹果和Google进行评论。
- 每次不构建和上传我们的应用程序到应用商店和Google Play。
我们只能拥有1个应用程序,该应用程序消耗了远程托管的Micro Frontend。可以随时更改微端口(假设我们不添加任何新的本地功能)。
我希望本教程对您有用!