使用Next.js和电容器构建本地移动应用程序
#javascript #网络开发人员 #nextjs #电容器

如果您正在使用Next.js来构建Web应用程序,则可以轻松地从电容器中受益,并使您的Web应用程序成为本机移动应用程序,而无需任何重大更改或学习新事物!

我以前曾谈论过how to build a native mobile app using React with Capacitor,并且故意没有反应本机 - 您可以为大多数Next.js应用程序做同样的事情。

nextjs.capacitor-app

在本教程中,我们将从新的Next.js应用程序开始,然后使用电容器进入本地土地,最终还将Ionic添加为改进的移动UI,尽管最后一步是完全可选的。

关于电容器

与React Native不同,电容器可以简单地放入任何 Web项目中,并有助于将整个应用程序包装到本机WebView中。

电容器然后为您生成本机Xcode和Android Studio项目,然后仅将您的更改同步到该项目。

此外,您可以使用电容器插件(我们将要做)访问本机设备功能像摄像机通过JS桥。

由于电容器具有超级纤细的API,而且功能没有很多功能,因此将其集成到任何Web项目中非常容易,同时仍然为您提供了一个令人惊叹的本机移动应用程序。

准备您的下一个.js应用

有不同的方法来启动React应用程序,但是为了本教程,让我们使用最简单的方法,它将为我们提供一个空白的New Next.js应用程序:

npx create-next-app my-app

最终要构建一个本机移动应用程序,我们需要我们项目的导出,所以让我们向我们的 package.json 添加一个简单的脚本。构建和导出下一个项目:

  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "static": "next build && next export"
  },

执行命令时,我会出现错误,因为在此设置中图像优化不起作用。

因此,打开 next.config.js 并将其更改为:

/** @type {import('next').NextConfig} */
const nextConfig = {
    reactStrictMode: true,
    swcMinify: true,
    experimental: {
        images: {
            unoptimized: true
        }
    }
};

module.exports = nextConfig;

现在您可以安全地运行npm run static,您应该在项目的根部看到一个新的 文件夹。

此文件夹将稍后由电容器使用,但首先我们需要正确设置它。

将电容器添加到您的下一个。

要将任何Web应用程序都包装到本机移动容器中,我们需要采取几个步骤 - 但是必须只完成一个初始时间,以后就像运行sync命令一样容易。

首先,我们可以安装Capacitor CLI作为开发依赖关系,然后在我们的项目中初始化它 - 您可以在对话框中按Enter来使用名称和捆绑ID的Defualt值。

之后,我们需要为iOS和Android平台安装核心包和相应的软件包。

最后,您可以添加平台,电容器将为项目根部的每个平台创建文件夹:

# Install the Capacitor CLI locally
npm install -D @capacitor/cli

# Initialize Capacitor in your React project
npx cap init

# Install the required packages
npm install @capacitor/core @capacitor/ios @capacitor/android

# Add the native platforms
npx cap add ios
npx cap add android

在这一点

这些是真正的本地项目!

要打开Android项目,您应该安装Android Studio,对于iOS,您需要在Mac上安装Xcode

此外,您还应该在项目中看到 Capacitor.config.ts ,该>具有在同步过程中使用的一些基本设置。您唯一需要担心的是 webdir ,它应该指向构建命令的输出 - 现在这是不正确的。

要解决此问题,打开 Capacitor.config.json 并更改 webdir

{
    "appId": "com.example.app",
    "appName": "my-app",
    "webDir": "out",
    "bundledWebRuntime": false
}

现在您可以通过运行以下命令来尝试一下:

npm run static
npx cap sync

第一个命令将简单地构建您的下一个项目。JS项目并导出静态构建,而第二个命令将所有Web代码同步到本机平台的正确位置,以便它们可以显示在应用程序中。

另外,同步命令可能会更新本机平台并安装插件,因此,当您安装新的Capacitor plugins时,该再次运行Sync。

没有注意到您现在已经完成,所以让我们在设备上查看应用程序!

构建和部署本地应用程序

您现在需要 xcode iOS和 Android Studio 用于机器上的Android应用程序。此外,如果您想在App Store上构建和分发应用程序,则需要加入Apple Developer程序,而Google Play商店也是如此。

如果您从未触摸过本地移动项目,则可以通过电容器CLI轻松打开两个本机项目:

npx cap open ios
npx cap open android

在Android Studio内部,您现在只需要等到一切准备就绪,您可以将应用程序部署到连接的设备而无需更改任何设置!

android-studio-deploy-angular

在Xcode内部几乎相同,但是如果您将应用程序部署到真实设备,而不仅仅是模拟器,则需要设置签名帐户。 XCode如果您从未完成过,则指导您完成此操作(但再次,您需要加入开发人员程序)。

之后,它就像在连接的设备上进行播放并运行应用程序一样容易,您可以在顶部进行选择! xcode-deploy-app-angular

恭喜,您刚刚将下一个。JSWeb应用程序部署到移动设备!

next-mobile-app,但坚持下去,在开发过程中,还有一种方法可以更快地做到这一点...

电容器现场重新加载

到目前为止,您已经习惯于使用所有现代框架进行热重新加载,并且在移动设备上甚至可以在最低限度的努力上具有相同的功能

这个想法是在您的网络上使用Live Reload 在本地服务的应用程序,并且电容器应用程序将简单地加载该URL的内容。

第一步是弄清楚您的本地IP,您可以通过运行:
在Mac上获得Mac。

ipconfig getifaddr en0

在Windows上,运行ipconfig并查找IPv4地址。

现在,我们只需要告诉电容器直接从该服务器加载应用程序,我们可以在我们的 Capacitor.config.ts 中使用另一个条目:

import { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
    appId: 'com.example.app',
    appName: 'my-app',
    webDir: 'out',
    bundledWebRuntime: false,
    server: {
        url: 'http://192.168.x.xx:3000',
        cleartext: true
    }
};

export default config;

确保您使用正确的IP和端口,我只是在此处使用默认的Next.js端口。

要应用这些更改,我们现在可以复制对本机项目的更改:

npx cap copy

副本大多喜欢同步,但仅在Web文件夹的更改和config,而不是更新本机项目上。

现在,您可以通过Android Studio或Xcode再部署应用程序,然后更改React App中的某些内容 - 该应用将自动重新加载并显示更改!

注意:如果您安装了诸如相机之类的新插件,这仍然需要重建本机项目,因为本地文件已更改,无法飞行。

使用电容器插件

我们已经嘲笑了几次,现在让我们查看电容器插件的用法。为此,我们可以通过运行安装一个非常简单的操作:

npm i @capacitor/share

Share plugin没有什么想象的,但是无论如何它提出了本地共享对话!为此,我们现在只需要导入软件包并从我们的应用程序调用share()函数,所以让我们更改 pages/index.js.js

import Head from 'next/head';
import styles from '../styles/Home.module.css';
import { Share } from '@capacitor/share';

export default function Home() {
    const share = async () => {
        await Share.share({
            title: 'Simons YT Channel',
            text: 'Learn to build awesome mobile apps!',
            url: 'https://www.youtube.com/simongrimmdev_',
            dialogTitle: 'Share with friends'
        });
    };

    return (
        <div className={styles.container}>
            <Head>
                <title>Create Next App</title>
                <meta name="description" content="Generated by create next app" />
                <link rel="icon" href="/favicon.ico" />
            </Head>

            <main className={styles.main}>
                <h1 className={styles.title}>
                    Welcome to <a href="https://nextjs.org">Simonics!</a>
                </h1>

                <p className={styles.description}>
                    <h2>Cool channel</h2>
                    <a onClick={() => share()}>Share now!</a>
                </p>
            </main>
        </div>
    );
}

如前所述,安装新插件后,我们需要运行一个同步,然后将应用程序重新部署到我们的设备:

npx cap sync

现在点击该按钮并见证美丽的本地共享对话框!

next-capacitor-share

但是,该按钮在没有任何样式的情况下看起来不友好,所以让我向您介绍我最喜欢的UI Component库的Web Apps(无双关语)。

添加离子UI

我已经在Ionic工作了多年,以构建很棒的跨平台应用程序,如果您想要适应iOS和Android特定样式的非常出色的移动UI,这是最好的选择之一。

我什至运行full blown online school where you can learn everything Ionic

要使用它,我们只需要安装离子React软件包:

npm install @ionic/react

此外,离子通常会使用Ionicons发货,Ionicons是一个很棒的图标库,再次适应了它正在运行的平台。我们还通过运行添加:

npm install ionicons

由于接下来要处理构建和导出与通常的略有不同,所以我们还需要另一个插件来修复一个错误,如果我们想使用任何离子组件,我们现在就会得到它。为此,安装以下软件包:

npm install next-transpile-modules

现在,我们需要在 next.config.js 之类的Ionic中包含包装和所有库。

const withTM = require('next-transpile-modules')([
    '@ionic/react',
    '@ionic/core',
    '@stencil/core',
    'ionicons'
]);

/** @type {import('next').NextConfig} */
const nextConfig = {
    reactStrictMode: true,
    swcMinify: true,
    experimental: {
        images: {
            unoptimized: true
        }
    }
};

module.exports = withTM(nextConfig);

觉得不酷,但是在写作时,必须使用next.js!

使用离子UI组件。

因为我们没有足够的疼痛,因此使用服务器端渲染时的离子组件水合也存在问题,因此我们有效地需要关闭SSR。

我发现最有效的是described in this article,所以让我们创建一个新文件组件/nossrwrapper.jsx 并插入以下内容:

import dynamic from 'next/dynamic';
import React from 'react';

const NonSSRWrapper = (props) => <React.Fragment>{props.children}</React.Fragment>;
export default dynamic(() => Promise.resolve(NonSSRWrapper), {
    ssr: false
});

现在,我们可以用此包装器包围其余的组件并修复一个错误 - 但是我们还需要照顾实际加载离子及其样式!

为此,我们可以带来一堆CSS导入和最重要的调用setupIonicReact(),因为否则您会看到一个空白的白页。

为此,打开页面/_app.js 并将其更改为:

import '../styles/globals.css';
import Head from 'next/head';
/* Core CSS required for Ionic components to work properly */
import '@ionic/react/css/core.css';

/* Basic CSS for apps built with Ionic */
import '@ionic/react/css/normalize.css';
import '@ionic/react/css/structure.css'; // Remove if nothing is visible
import '@ionic/react/css/typography.css';

/* Optional CSS utils that can be commented out */
import '@ionic/react/css/padding.css';
import '@ionic/react/css/float-elements.css';
import '@ionic/react/css/text-alignment.css';
import '@ionic/react/css/text-transformation.css';
import '@ionic/react/css/flex-utils.css';
import '@ionic/react/css/display.css';
import { setupIonicReact } from '@ionic/react';

setupIonicReact();

import NonSSRWrapper from '../components/NoSSrWrapper';

function MyApp({ Component, pageProps }) {
    return (
        <>
            <Head>
                <title>Create Next App</title>
                <meta name="description" content="Generated by create next app" />
                <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
                <link rel="icon" href="/favicon.ico" />
            </Head>
            <NonSSRWrapper>
                <Component {...pageProps} />
            </NonSSRWrapper>
        </>
    );
}

export default MyApp;

我还在此处添加了一点 meta标签来设置视口拟合,因为离子组件会更喜欢这种设置。相信我。

现在我们可以自由使用任何Ionic UI components,因此我只是在应用程序中添加一个小标头栏,然后更改一个单击处理程序以使用真实的按钮UI。

要使用这些组件,我们需要单独导入它们,并且由于您可能不喜欢网络上的移动友好状态栏,因此您也可以用一些平台检查 ,这是电容器核心的一部分包装 - 非常方便!

通过将您的页面/index.js 更改为
来完成本教程:

import Head from 'next/head';
import styles from '../styles/Home.module.css';
import { Share } from '@capacitor/share';
import { IonHeader, IonTitle, IonToolbar } from '@ionic/react';
import { Capacitor } from '@capacitor/core';

export default function Home() {
    const share = async () => {
        await Share.share({
            title: 'Simons YT Channel',
            text: 'Learn to build awesome mobile apps!',
            url: 'https://www.youtube.com/simongrimmdev_',
            dialogTitle: 'Share with freiends'
        });
    };

    return (
        <div>
            <Head>
                <title>Create Next App</title>
                <meta name="description" content="Generated by create next app" />
                <link rel="icon" href="/favicon.ico" />
            </Head>
            {Capacitor.isNativePlatform() && (
                <IonHeader>
                    <IonToolbar color="primary">
                        <IonTitle>Simons Capacitor App</IonTitle>
                    </IonToolbar>
                </IonHeader>
            )}

            <main className={styles.main}>
                <h1 className={styles.title}>
                    Welcome to <a href="https://nextjs.org">Simonics!</a>
                </h1>
                <ion-button color="success" onClick={() => share()}>
                    Share now!
                </ion-button>
            </main>
        </div>
    );
}

如果您的实时重新加载在所有安装之后都不同步,则重新启动所有内容,然后您应该看到一个有点像本机外观的移动应用程序,并使用Next.js和电容器构建!

结论

电容器是基于您现有的Web项目构建本机应用程序时最简单的解决方案。

其他常见的反应解决方案将是本机的,但是通常只能共享逻辑,而不是实际的UI代码,而我们实际上不必触摸UI,如果我们使用电容器。

如果您喜欢本教程或有其他问题,请在下面发表评论!