Flutter隨筆(二)——使用Flutter Web + Docker + Nginx打造一個簡單的Web專案
前言
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專案到部署至伺服器的整個流程!