前言

  Flutter作为一个跨平台UI框架,功能十分强大,仅用一套代码便能编译出Android、iOS、Web、windows、macOS、Windows、Linux等平台上的应用,各平台应用体验高度一致,目测前途一片光明,形势一片大好。

  Flutter支持Android和iOS已经很长一段时间了,相信很多同学对使用Flutter开发Android和iOS应用都已经驾轻就熟了,今天我们就来体验一把Flutter Web。目标是创建一个简单的Flutter Web项目,然后打包部署到服务器,通过浏览器进行访问。

1.创建Flutter工程

  首先我们需要创建一个Flutter工程。我使用了Android Studio来创建工程,如下:

  上图中需要注意的地方是Platforms,在Platforms栏中我们要选择程序运行的平台,因为我们最终要打包出Web项目,所以我们务必勾选Web选项。
  工程创建好之后的目录结果如下:

  除了我们熟悉的Android和iOS目录外,还多了Web目录,Web目录下存放了Web项目所需要的全部文件。

2.编写flutter代码

  接下来,我们编写flutter代码,代码非常简单,仅实现了在主页点击按钮跳转到对应子页面的功能。
  主页 main.dart 的代码如下:

import 'package:flutter/material.dart';

import 'ChildPage.dart';

void main() {
runApp(MyApp());
} class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'xy_flutter',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'xy_flutter'),
);
}
} class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key); final String title;
final List<HomeMenu> menus = [
HomeMenu('page1', '页面1'),
HomeMenu('page2', '页面2'),
HomeMenu('page3', '页面3'),
]; @override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: ListView.builder(
itemCount: menus.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(menus[index].title),
onTap: () {
HomeMenu homeMenu = menus[index];
String id = homeMenu.id;
String title = homeMenu.title;
if (id == 'page1') {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChildPage(title: title)));
} else if (id == 'page2') {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChildPage(title: title)));
} else if (id == 'page3') {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChildPage(title: title)));
}
},
);
}),
);
}
} class HomeMenu {
String id;
String title; HomeMenu(this.id, this.title);
}

  子页面 child_page.dart 的代码如下:

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; class ChildPage extends StatefulWidget {
final String title; const ChildPage({Key key, this.title}) : super(key: key); @override
State<StatefulWidget> createState() {
return _ChildPageState();
}
} class _ChildPageState extends State<ChildPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.title)), body: Text(widget.title));
}
}

3.打包Web工程

  在工程根目录下执行以下命令进行编译打包:

flutter build web

  命令执行成功之后,编译生成的文件被输出到了 工程根目录/build/web/ 目录下,如下:

4.上传Web工程到服务器

  通过文件传输工具(例如FileZilla等)将编译后生成的所有文件上传到服务器。我上传到服务器的路径为 home/ubuntu/docker/xy_flutter/web/home/ubuntu/docker/xy_flutter/web/ 目录和工程编译出来的web目录对应,即 home/ubuntu/docker/xy_flutter/web/ 目录下的文件和工程编译出来的web目录下的文件完全一致。

5.创建Nginx Docker容器

  接下来,我们在服务器中创建一个Nginx的Docker容器,用来运行Web项目。
  如果服务器还没有安装Docker,需要先安装Docker,关于如何安装Docker可以参考我之前整理的资料 Docker游记1——安装Docker 
  如果已经安装好了Docker,但还没有拉取Nginx的Docker镜像,需要先拉取一下镜像,可以通过如下命令拉取最新的Nginx Docker镜像:

docker pull nginx:latest

  镜像拉取下来之后,可以通过如下命令查看当前所有已拉取下来的镜像:

docker images

  得到的结果如下:

REPOSITORY     TAG       IMAGE ID       CREATED        SIZE
nginx latest 87a94228f133 2 days ago 133MB

  我们可以看到已经有Nginx的镜像了。
  接着我们利用拉取下来的镜像创建一个容器,执行以下命令:

docker run --name xy_flutter -p 8088:80 -d nginx

  这行命令表示使用Nginx镜像创建并持续运行一个名为xy_flutter的容器,并将服务器的8088端口映射到容器的80端口。创建好之后,可以通过以下命令查看创建好的容器:

docker ps

  结果如下:

CONTAINER ID   IMAGE               COMMAND                  CREATED         STATUS         PORTS                                       NAMES
0c6f697a8e0c nginx "/docker-entrypoint.…" 5 seconds ago Up 3 seconds 0.0.0.0:8088->80/tcp, :::8088->80/tcp xy_flutter

  容器创建好之后,我们就可以通过浏览器访问容器对应的Nginx服务了,因为我的服务器地址IP地址是 http://49.234.163.66/ ,容器映射的服务器端口是8088,所以访问地址是 http://49.234.163.66:8088/ ,访问后跳转的页面如下:

  已经看到Nginx在欢迎我们了!

6.部署Web工程

  我们通过浏览器访问Nginx服务时,跳转的页面其实是容器中的 /usr/share/nginx/html/index.html 文件,我们可以进入容器查看。
  执行以下命令进入容器:

docker exec -it {容器ID} /bin/bash

  进入容器后,我们通过`cd`命名访问 /usr/share/nginx/html/ 目录,目录中的文件如下:

  要部署Web工程,把Web工程中的所有文件复制到容器的 /usr/share/nginx/html/ 目录就可以了,Web工程中的index.html会覆盖 /usr/share/nginx/html/index.html 文件。我们通过如下命令把服务器本地的文件复制到容器中:

docker cp {服务器中Web工程目录下的所有子文件} {容器ID}:/usr/share/nginx/html

  我的服务器中Web工程目录下的所有子文件是 home/ubuntu/docker/xy_flutter/web/. ,容器ID是 0c6f697a8e0c ,所以我执行的命令是:

docker cp home/ubuntu/docker/xy_flutter/web/. 0c6f697a8e0c:/usr/share/nginx/html

7.部署完成

  在上述步骤中,我们已经将Web工程拷贝到容器中的指定位置了,到这里部署工作其实也就完成了,我们再次在浏览器中输入 http://49.234.163.66:8088/ 访问,可以看到已经可以打开我们的Web工程了,如下:

  至此,我们就完成了从创建Flutter Web项目到部署至服务器的整个流程!

最后奉上项目地址

Flutter随笔(二)——使用Flutter Web + Docker + Nginx打造一个简单的Web项目的更多相关文章

  1. Web开发之tomcat配置及使用(环境变量设置及测试,一个简单的web应用实例)

    Tomcat的配置及测试: 第一步:下载tomcat,然后解压到任意盘符 第二步:配置系统环境变量 tomcat解压到的D盘 (路径为: D:\tomcat), 配置环境变量: 启动tomcat需要两 ...

  2. Docker容器技术-创建一个简单的Web应用

    一.创建一个简单的Web应用 1.identicon 基于某个值而自动产生的图像,这个值是IP地址或用户名的散列值. 用途: 通过计算用户名或IP地址的散列值,在网站上提供用于识别用户的图像,以及自动 ...

  3. docker nginx实现一个主机部署多个站点

    原文:docker nginx实现一个主机部署多个站点 在某站租赁的虚拟机快到期了,续费得花200多,想到在阿里云新买的服务器,不如把这个也转移过去.域名我就用真实的吧,大家别黑我网站就好了,谢谢各位 ...

  4. django创建一个简单的web站点

    一.新建project 使用Pycharm,File->New Project…,选择Django,给project命名 (project不能用test命名)   新建的project目录如下: ...

  5. 使用Servlet和JSP实现一个简单的Web聊天室系统

    1 问题描述                                                利用Java EE相关技术实现一个简单的Web聊天室系统,具体要求如下. (1)编写一个登录 ...

  6. 自己动手模拟开发一个简单的Web服务器

    开篇:每当我们将开发好的ASP.NET网站部署到IIS服务器中,在浏览器正常浏览页面时,可曾想过Web服务器是怎么工作的,其原理是什么?“纸上得来终觉浅,绝知此事要躬行”,于是我们自己模拟一个简单的W ...

  7. 用Python写一个简单的Web框架

    一.概述 二.从demo_app开始 三.WSGI中的application 四.区分URL 五.重构 1.正则匹配URL 2.DRY 3.抽象出框架 六.参考 一.概述 在Python中,WSGI( ...

  8. IntelliJ IDEA 15 部署Tomcat及创建一个简单的Web工程

    一.部署Tomcat 二.创建一个简单的Web工程 2.1创建一个新工程 创建一个新工程 设置JDK及选择Web Application (创建的是Web工程) 点击Next,选择工作空间,起个工程名 ...

  9. (转)Web Service入门简介(一个简单的WebService示例)

    Web Service入门简介 一.Web Service简介 1.1.Web Service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从I ...

随机推荐

  1. 数据库CPU 100%处理记录

    问题描述 2020年7月13日一大早收到告警,测试环境数据库CPU告警. 登录aws查看监控如下图   问题分析 出现这种cpu 100%的问题,都是因为sql性能问题导致的, 主要表现于 cpu 消 ...

  2. shell循环语句until

    until 条件 do 执行命令 done until 循环与 while 循环在处理方式上刚好相反. 当条件成立的时候,停止循环.

  3. UNION / UNION ALL 区别

    Union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序: Union All:对两个结果集进行并集操作,包括重复行,不进行排序: 使用union all: select top 5 ...

  4. 未能找到源类型“DbSet<T>”的查询模式的实现。未找到“Select”

    使用EF6.0的模型优先模式进行开发,遇到了报错,如下图 后来发现是没引用using System.Linq; 引用后就不报错了

  5. java多线程 synchronized 与lock锁 实现线程安全

    如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的. 通过卖火车票的例子 火车站要卖票,我们模 ...

  6. Identity用户管理入门四(修改、删除用户)

    修改用户不能修改Id及用户名所以创建视图模型时需要去除,新增用户跟修改用户基本视图一直,所以不再做演示 一.新建UpdateUserViewModel视图模型 using System.Compone ...

  7. 硕盟SM-T54(TYPE C转HDMI+VGA+USB3.0+PD3.0)

    硕盟SM-T54是一款TYPE C转HDMI+VGA+USB3.0+PD3.0四口扩展坞,您可以将含有USB 3.1协议的电脑主机,通过此产品连接到具有HDMI或VGA的显示器.电视机或其他显示设备. ...

  8. 硕盟SM-T54| TYPE C转HDMI+VGA+USB3.0+PD3.0四合一多功能扩展坞

    硕盟SM-T54是一款 TYPE C转HDMI+VGA+USB3.0+PD3.0四合一多功能扩展坞,支持四口同时使用,您可以将含有USB 3.1协议的电脑主机,通过此产品连接到具有HDMI或VGA的显 ...

  9. Prism+WPF使用DependencyInjection实现AutoMapper的依赖注入功能

    前言 在使用PRISM+WPF开发项目的过程中,需要使用AutoMapper实现对象-对象的映射功能.无奈PRISM没有相关对AutoMapper相关的类库,于是转换一下思想,在nuget 中存在有关 ...

  10. weblogic从ssrf到redis获取shell

    一.环境搭建和知识储备 1.1.影响版本 漏洞编号:CVE-2014-4210 weblogic 10.0.2.0 weblogic 10.3.6.0 1.2.Docker搭建环境 1.进入vulhu ...