1 Introduction
First of all, let me explain that this article is for client development students ( Flutter
it is best to have a foundation). Flutter
Although it was born from Google
the Chrome
team, everyone knows that Flutter
the first supported platform is Android
and iOS
, and the core maintenance platform is still Android
and iOS
. dart
The learning cost of the language is not high, Flutter
and the responsive UI has great similarities with Compose
and SwiftUI
, and the overall architecture idea is more biased towards the client-side model. In addition, in order to realize many hardware or Native
related basic functions, professional client-side development knowledge is required, so Flutter
it is more recognized and used by client-side development students (in our team, Flutter
it is already a necessary basic skill for client-side development students). Although Flutter
the biggest highlight is cross-end, in fact, cross-end between client and web
end is not common due to the large difference. Therefore, under this background, we Flutter
did not initially web
make efforts on the end. But Flutter
it is the gene that it carries web
, so the stable version Flutter2
was finally released when it was released . So since the cross-end between the client and the end is not common, front-end developers probably won’t use it for development (it’s really unnecessary, the package size increases and there is a certain performance loss, and you need to learn new languages and development ideas, native development is not good), what’s the use ? With this in mind, I haven't investigated end-to-end support for a long time after use. However, with the development and changes of business and internal needs,web
web
Flutter
web
Flutter Web
Flutter
web
Flutter Web
The advantages are also gradually revealed. Let me talk about the use Flutter Web
of the main three scenarios.
2. Flutter Web usage scenarios
- 1. The internal web requirements of the client team : In the context of reducing costs and increasing efficiency in the post-epidemic era, we will use more self-developed tools. The use of self-developed tools and the visualization of results are usually displayed in the form of web pages. Although there are front-end development students in the team, considering that self-developed tools are more attempts within the group and have nothing to do with business, naturally front-end students should not be allowed to undertake this part of the work. The learning cost of web development is low for client- side students , and they
Flutter Web
can develop web pages quickly .Vue
web
css
Flutter
Flutter
Flutter
- 2. Web business requirements that do not require long-term maintenance :
web
the terminal carries many activity requirements, which are characterized by strong timeliness, simple functions, and no long-term maintenance. However, these needs are often generated in large quantities during a certain period of time (such as some activities or lists during the holidays), or suddenly (such as instant demand for speculation). The insertion of these tasks sometimes leads toweb
the delay of some long-term iterative end requirements, which affects the overall schedule of the team. Since the development of these requirements is not difficult, the performance requirements are not high, and long-term maintenance is not required (meaning that even if no one in the team uses itFlutter
orFlutter Web
it will hang up one day), it is especially suitable for apportionment to client development. After the client development students joined in, they shared part of the work equally to improve the efficiency of the entire team. - 3. Cross-end between the client and the web : I personally think that this part of the demand is relatively small. But if there is such a demand, then we can save a lot of human resources to redevelop a set of
web
terminals.
Okay, now that there is a demand, let's walk through Flutter Web
the process of how to develop, deploy and go online.
3. Creation and business realization of Flutter Web project
3.1. Create and run
We use Android Studio
as an IDE to Flutter 3.10.5
create a Flutter Web
project based on the version.
Create one New Flutter Project
, Platforms
just check it when selecting Web
, and go straight to it Create
.
web
Then we found an extra folder in the project directory :
If you want to run
get up, just select chrome
the browser and click run
:
Then we can see the running results in the browser. Of course, we can also open the developer mode for easy viewing and debugging:
After this part runs through, congratulations that you can happily use Flutter
the development webpage. Next, we will implement a business requirement: create a webpage search function.
I won’t go into details about the development and implementation of business functions. You can tell Flutter
the students who have done development that there is no difference. The basic configuration/network module/data sharing/routing can be packaged as you want. I just took the code of the corresponding module of the previous client project and modified it slightly Flutter
. UI
The development on the website is also how to layout and layout, and the business development experience is no different from that of the client Flutter
.
3.2. Debugging
How to debug after running through?
If you are familiar with the browser developer mode, you can directly use the browser to debug. It is no problem to type log
or to see the source code, and you can capture packets:debug
Of course , the Android Studio
client -side students may not be familiar with the browser developer mode .Flutter
web
3.3.window
When developing on web
the end, we usually use window
objects to perform some operations. window
Object represents a browser window or a frame. Objects are required for common event
operations such as monitoring and opening web pages window
.
Flutter
The built-in dart:html
package window
, we can use it to realize the acquired window
properties or window
operate on them, such as:
//打开网页
window.open("http://www.baidu.com","");
//监听event
window.addEventListener("mousedown", (event) => {
//do something
});
In addition window
, it can also help us distinguish the operating environment.
3.4. Browser operating environment distinction
The client usually needs to distinguish between Android
these iOS
two different operating environments, while web
the client needs to UA
distinguish between different browser environments, and the UI/logic in different environments will be different. In China, we most often need to distinguish between PC
end/mobile Android
end/end/ iOS
end/WeChat webpage/WeChat applet. Then we can define a class and use it window.navigator.userAgent
to distinguish these environments:
import 'dart:html';
class DeviceUtil {
static final DeviceUtil _instance = DeviceUtil._private();
static DeviceUtil get() => _instance;
factory DeviceUtil() => _instance;
late String ua;
DeviceUtil._private() {
ua = window.navigator.userAgent;
}
//移动端
isMobile() {
return RegExp(
r'phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone')
.hasMatch(ua);
}
//iOS端
isIos() {
return RegExp(r'\(i[^;]+;( U;)? CPU.+Mac OS X').hasMatch(ua);
}
//Android端
isAndroid() {
var isAndroid = ua.contains("Android") || ua.contains("Adr");
return isAndroid;
}
//微信环境
isWechat() {
return ua.contains("MicroMessenger");
}
//微信小程序环境
isMiniprogram() {
if (ua.contains("micromessenger")) {
//微信环境下
if (ua.contains("miniprogram")) {
//小程序;
return true;
}
}
return false;
}
}
3.5. Development/test/production environment distinction
Like the client, web
the client also needs to distinguish development/test/production environments. In the same way as the client, we can still distinguish the environment by configuring different entry files. like:
- main_dev.dart
void main() {
AppConfig.init(ConfigType.dev);
root_main.main();
}
- main_test.dart
void main() {
AppConfig.init(ConfigType.test);
root_main.main();
}
- main_online.dart
void main() {
AppConfig.init(ConfigType.online);
root_main.main();
}
Now AppConfig.init()
you can make different configurations according to different environments.
3.6. Other commonly used libraries or plug-ins
I won’t introduce libraries such as data sharing/network/UI/animation, because these libraries are not related to the platform, just use what you are familiar with. The following is an introduction to the plug-ins that need to be used to implement some browser-related functions.
- When shared_preferences
is developed on the client side, we know that if we need to implement lightweight local serialization for some datashared_preferences
, we can use it to achieve theAndroid
correspondingSharedPreferences
sum . When developing, we know that if we need to serialize some data locally, we can use it . In fact , plug-ins are also supported , and their implementation is also encapsulated . I won't go into details about the use of , I'm already very familiar with it.iOS
NSUserDefaults
web
LocalStorage
Flutter
shared_preferences
web
LocalStorage
shared_preferences
- image_picker_for_web
comes from our familiarimage_picker
plugin. Depending on the browser, it supports or partially supports taking photos/shooting videos/reading pictures/reading videos, etc. - The js
plugin is used to use annotations to help youDart
callJavaScript API
orJavaScript
callDart API
.
Well, so far, I think it is no longer a problem to use Flutter
and develop a regular business. web
Next, let's discuss how to package and deploy online?
4. Package and deploy online
4.1. Packaging
Flutter Web
The packaging is very simple, run:
flutter build web
That's it. But this is obviously not enough, because we need to distinguish the environment to get through the package.
In the previous chapter, we configured different entry files. Let’s take the dev
environment as an example. The entry file is main_dev
, then our packaging command becomes:
flutter build web -t lib/main_dev.dart
After the execution of this line of command is completed, an error is reported, and the error message is as follows:
This is an icon data loading problem, we can add --no-tree-shake-icons. Execute the command as follows:
flutter build web -t lib/main_dev.dart --no-tree-shake-icons
Then we will find this folder build
under the folder of the project root directory , which corresponds to the folder typed out by the front end . Contains the following files:web
web
dist
The compiled product is available, so how to deploy it?
4.2. Deployment
The official deployment method is as follows:
https://flutter.cn/docs/deployment/web#deploying-to-the-web
After reading the official documentation, I found that these three deployment methods are not suitable for our project. Due to CDN
the advantages of improving website performance and user experience, and reducing the load on the original server, our team has already built a CDN
deployment platform. That being the case, our deployment plan also needs to rely on this aspect.
4.2.1. Solution 1 - Modify index.html
Let me briefly explain FlutterWeb
the compiled product first, with two key points: flutter.js
and main.dart.js
. Which flutter.js
is the entry js
file, we can open web
the directory index.html
:
<!DOCTYPE html>
<html>
<head>
<!--
If you are serving your web app in a path other than the root, change the
href value below to reflect the base path you are serving from.
The path provided below has to start and end with a slash "/" in order for
it to work correctly.
For more details:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
This is a placeholder for base href that will be replaced by the value of
the `--base-href` argument provided to `flutter build`.
-->
<base href="$FLUTTER_BASE_HREF">
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="A new Flutter project.">
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="flutter_web">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png"/>
<title>flutter_web</title>
<link rel="manifest" href="manifest.json">
<script>
// The value below is injected by flutter build, do not touch.
var serviceWorkerVersion = null;
</script>
<!-- This script adds the flutter initialization JS code --></script>-->
<script src="flutter.js" defer></script>
</head>
<body>
<script>
window.addEventListener('load', function(ev) {
// Download main.dart.js
_flutter.loader.loadEntrypoint({
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
},
onEntrypointLoaded: function(engineInitializer) {
engineInitializer.initializeEngine({
}).then(function(appRunner) {
appRunner.runApp();
});
}
});
});
</script>
</body>
</html>
See <script src="flutter.js" defer></script>
this line. It ismain.dart.js
the file that our dart
business code is compiled into js
. and other files flutter.js
will be loaded . main.dart.js
By default, flutter.js
all files, including resource files ( assets
), are loaded using relative paths. The first is loadEntrypoint ()
to load main.dart.js
this file through the method:
//flutter.js
async loadEntrypoint(options) {
const {
entrypointUrl = `${
baseUri}main.dart.js`, onEntrypointLoaded } =
options || {
};
return this._loadEntrypoint(entrypointUrl, onEntrypointLoaded);
}
But we found that it seems entrypointUrl
that we can pass it by ourselves, so we found 自定义web应用初始化
the link from the official website document:
https://flutter.cn/docs/platform-integration/web/initialization
has the following parameters to pass:
Where loadEntrypoint()
methods can be passed entrypointUrl
parameters to specify main.dart.js
the path. The method initializeEngine()
can assetBase
specify CDN
the resource path by passing parameters. main.dart.js
So it seems that we can solve the problem of loading and CDN
resource paths by setting these two parameters as absolute paths . It should be noted that initializeEngine()
the method is Flutter3.7.0
only supported at the beginning.
Let's change it index.html
:
window.addEventListener('load', function(ev) {
// Download main.dart.js
_flutter.loader.loadEntrypoint({
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
},
entrypointUrl: "YOUR_CDN_ABSOLUTE_PATH/main.dart.js",
onEntrypointLoaded: function(engineInitializer) {
engineInitializer.initializeEngine({
assetBase: "YOUR_CDN_ABSOLUTE_PATH"
}).then(function(appRunner) {
appRunner.runApp();
});
}
});
});
If we make another package, it will still report an error and cannot find it flutter.js
, or because of the path problem. The processing method is simpler, just index.html
configure it as an absolute path in . Icon-192.png
In addition , we found favicon.png
that manifest.json
these files are also relative paths, so we change them to absolute paths at once:
<head>
<!--
If you are serving your web app in a path other than the root, change the
href value below to reflect the base path you are serving from.
The path provided below has to start and end with a slash "/" in order for
it to work correctly.
For more details:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
This is a placeholder for base href that will be replaced by the value of
the `--base-href` argument provided to `flutter build`.
-->
<base href="$FLUTTER_BASE_HREF">
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="A new Flutter project.">
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="flutter_web">
<link rel="apple-touch-icon" href="YOUR_CDN_ABSOLUTE_PATH/icons/Icon-192.png">
<!-- Favicon -->
<link rel="icon" type="image/png" href="YOUR_CDN_ABSOLUTE_PATH/favicon.png"/>
<title>flutter_web</title>
<link rel="manifest" href="YOUR_CDN_ABSOLUTE_PATH/manifest.json">
<script>
// The value below is injected by flutter build, do not touch.
var serviceWorkerVersion = null;
</script>
<!-- This script adds the flutter initialization JS code -->
<script src="YOUR_CDN_ABSOLUTE_PATH/flutter.js" defer></script>
</head>
Make another package and upload it CDN
, um, everything is normal~
It looks perfect up to here, but suddenly I think it’s wrong. We distinguish between development/testing/production environments, and the corresponding CDN
paths are also different. The modification index.html
method specifies absolute paths, which do not meet our needs. After research, another way was found.
4.2.2 Scheme 2———base-href
Looking at index.html
the code again, I found the top note:
<!--
If you are serving your web app in a path other than the root, change the
href value below to reflect the base path you are serving from.
The path provided below has to start and end with a slash "/" in order for
it to work correctly.
For more details:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
This is a placeholder for base href that will be replaced by the value of
the `--base-href` argument provided to `flutter build`.
-->
<base href="$FLUTTER_BASE_HREF">
It probably means that we can flutter build
use the value --base-href
specified by the parameter when using the package base href
. Quickly check out base href
the relevant instructions:
The base tag is a base link tag and is a single tag. Used to change the parameter defaults for all link tags in the document. It can only be applied between tags and .
All [relative paths] on your web page will be prepended with the address pointed to by the base link when linking.
In this case, let's try it~
The packaging command is updated as follows:
flutter build web -t lib/main_dev.dart --base-href YOUER_CDN_PATH --no-tree-shake-icons
It should be noted that it is YOUER_CDN_PATH
not an absolute path, but a removed host
path. For example, your absolute path is:
https://cdn-path.com/your/business/path/dev/
Then yourYOUER_CDN_PATH
should be:
/your/business/path/dev/
Make another package and upload it to the CDN
website, everything is really perfect~
5. Summary
We have Flutter
completed web
the development of a project and deployed it to CDN
. In addition, web
there are some common problems on the end, such as cross-domain problems, which need to be solved together with the server-side classmates, and they are all ready-made solutions. FlutterWeb
In fact, it has been stable for a long time, but it has not developed due to the lack of usage scenarios. But existence is reasonable. For our client development, after we have acquired the skills, we can completely expand our business scope, carry out partial end development, and add more business possibilities for our team, Flutter
except for the familiar Android
and cross-end development.iOS
web
at last
If you want to become an architect or want to break through the 20-30K salary range, then don't be limited to coding and business, but you must be able to select models, expand, and improve programming thinking. In addition, a good career plan is also very important, and the habit of learning is very important, but the most important thing is to be able to persevere. Any plan that cannot be implemented consistently is empty talk.
If you have no direction, here I would like to share with you a set of "Advanced Notes on the Eight Major Modules of Android" written by the senior architect of Ali, to help you organize the messy, scattered and fragmented knowledge systematically, so that you can systematically and efficiently Master the various knowledge points of Android development.
Compared with the fragmented content we usually read, the knowledge points of this note are more systematic, easier to understand and remember, and are arranged strictly according to the knowledge system.
Welcome everyone to support with one click and three links. If you need the information in the article, you can directly scan the CSDN official certification WeChat card at the end of the article to get it for free↓↓↓
PS: There is also a ChatGPT robot in the group, which can answer your work or technical questions