前面我们完成了项目化
和在线部署
,完成后,通常我们会进入新的版本迭代阶段,比如,我们的weather
项目,
现在要增加PM2.5
具体数值显示这个需求。
于是,我们遇到一个问题就是前端然后在部署的情况下,开发环境的情况下确保代码运行良好,虽然我们可以在chrome下 确定页面样式问题,但是假设天气数据是来源于我们的服务端,服务端需要我们提供移动客户端的登录态才能调用,这时候 App里就需要提供开发环境。
简单的说:在开发环境下我们打开天气的页面时最好访问的是我们webpack开发服务器
实现方式:移动客户端可以打包一个开发环境包,这个包运行起来可以配置指向webpack服务端
Android开发环境
一般打开开发环境的方式有多种:
- 提供稳定的UI入口进入
- 摇一摇进入
- 开发环境悬浮按钮
这里我们使用摇一摇
进入
代码编写
MainActivity.kt
摇一摇
代码放在MainActivity
中
class MainActivity : WebActivity(), ShakeSensor.OnShakeListener {
private lateinit var shakeSensor: ShakeSensor
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 初始化摇一摇传感器
if (BuildConfig.DEBUG) {
shakeSensor = ShakeSensor(this)
shakeSensor.shakeListener = this
shakeSensor.register()
}
}
override fun onDestroy() {
super.onDestroy()
// 销毁
if (BuildConfig.DEBUG) {
shakeSensor.unregister()
}
}
override fun getLoadUrl(): String {
return WebManager.getWebUrl("home", "index.html")
}
override fun onShakeComplete(event: SensorEvent) {
// 摇一摇显示开发环境
AlertDialog.Builder(this)
.setTitle("打开开发环境?")
.setItems(arrayOf("取消", "确定")) { _, index ->
if (index == 1) {
gotoDevSettings()
}
}
.create()
.show()
}
private fun gotoDevSettings() {
// 摇一摇点确定后去DevSettingsActivity
startActivity(Intent(this, DevSettingsActivity::class.java))
}
}
::: tip 注意 这里用到了Android的传感器,实现摇一摇的动作代码在: ShakeSensor :::
DevSettingsActivity.kt
这次我们实现界面使用Android的新功能PreferenceScreen
首先,像添加okio
库依赖一样添加preference
依赖,这个库是官方提供的:
implementation("androidx.preference:preference:1.1.0-alpha04")
DevSettingsActivity:
package com.example.tobebigfe.web
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.PreferenceFragmentCompat
import com.example.tobebigfe.R
class DevSettingsActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_dev_settings)
title = "开发设置"
supportFragmentManager
.beginTransaction()
.add(R.id.settings_container, DevSettingsFragment())
.commit()
}
}
class DevSettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.dev_preferences, rootKey)
}
}
layout/activity_dev_settings.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:id="@+id/settings_container" xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
xml/dev_preferences.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory app:key="webDev" android:title="Web开发环境">
<SwitchPreferenceCompat
app:key="webDev.enabled"
app:title="开启开发模式"/>
<EditTextPreference
app:key="webDev.project"
app:title="项目"
app:useSimpleSummaryProvider="true"/>
<EditTextPreference
app:key="webDev.server"
app:title="服务器"
app:useSimpleSummaryProvider="true" />
</PreferenceCategory>
</PreferenceScreen>
WebManager.kt
object WebManager {
...
private lateinit var preferences: SharedPreferences
// 初始化
fun init(context: Context) {
preferences = PreferenceManager.getDefaultSharedPreferences(context)
...
}
// 根据id和page获取正式的url
fun getWebUrl(id: String, page: String): String {
// 判断设置的是不是开发项目
if (BuildConfig.DEBUG && preferences.isWebDevEnabled() && id == preferences.webDevProject()) {
return "http://${preferences.webDevServer()}/$id/dev/$page?t=" + System.currentTimeMillis()
}
return "${WebConst.WEB_BASE_URL}$id/${versionMap[id]}/$page"
}
...
}
private fun SharedPreferences.isWebDevEnabled(): Boolean {
return getBoolean("webDev.enabled", false)
}
private fun SharedPreferences.webDevProject(): String? {
return getString("webDev.project", null)
}
private fun SharedPreferences.webDevServer(): String? {
return getString("webDev.server", null)
}
最终代码结构
运行结果
摇一摇:
Android日志:
::: tip 注意
配置好的是本地的一个服务器地址和weather
项目,所以进weather
时加载的是开发环境的链接
:::
扩展阅读
iOS开发环境
学习 SwiftPackage 添加依赖
Swift Package Manager 是苹果提供的官方依赖管理器,并且 XCode11 之后对这个支持非常好
这次我们要依赖的是:github.com/neoneye/Swi…
一般我们选择Up to Next Minor
点 Finish
最后成功引入 SwiftyFORM
代码编写
一般打开开发环境的方式有多种:
- 提供稳定的 UI 入口进入
- 摇一摇进入
- 开发环境悬浮按钮
这里我们使用摇一摇
进入
ViewController.swift
摇一摇
代码放在ViewController
中
class ViewController : WebViewController {
override func getLoadUrl() -> String {
return WebManager.shared.getWebUrl(id: "home", page: "index.html")
}
override func viewDidLoad() {
super.viewDidLoad()
/**
开启摇动感应
*/
UIApplication.shared.applicationSupportsShakeToEdit = true
becomeFirstResponder()
}
override func motionBegan(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
// 识别到摇一摇
if motion == .motionShake {
showDevAction()
}
}
private func showDevAction() {
let actionSheet = UIAlertController(title: "摇一摇", message: nil, preferredStyle: .actionSheet)
let cancel = UIAlertAction(title: "取消", style: .cancel)
actionSheet.addAction(cancel)
let webDev = UIAlertAction(title: "进入开发环境?", style: .default) { action in
let navVC = UINavigationController(rootViewController: DevSettingsController())
self.present(navVC, animated: true, completion: nil)
}
actionSheet.addAction(webDev)
self.present(actionSheet, animated: true, completion: nil)
}
}
DevSettingsController.swift
这次我们实现界面使用SwiftyFORM
import Foundation
import UIKit
import SwiftyFORM
class DevSettingsController : FormViewController {
lazy var settings: UserDefaults = { return WebManager.shared.settings }()
lazy var enabledSwitch: SwitchFormItem = {
let instance = SwitchFormItem()
instance.title = "开启"
instance.setValue(settings.bool(forKey: "enabled"), animated: false)
instance.switchDidChangeBlock = {
self.settings.setValue($0, forKey: "enabled")
}
return instance
}()
lazy var projectTextField: TextFieldFormItem = {
let instance = TextFieldFormItem()
instance.title = "项目"
instance.placeholder = "未设置"
instance.textAlignment = .right
instance.value = self.settings.string(forKey: "project") ?? ""
instance.textDidChangeBlock = {
self.settings.setValue($0, forKey: "project")
}
return instance
}()
lazy var serverTextField: TextFieldFormItem = {
let instance = TextFieldFormItem()
instance.title = "服务器"
instance.placeholder = "未设置"
instance.textAlignment = .right
instance.value = self.settings.string(forKey: "server") ?? ""
instance.textDidChangeBlock = {
self.settings.setValue($0, forKey: "server")
}
return instance
}()
override func viewDidLoad() {
super.viewDidLoad()
self.title = "开发环境"
let leftCloseBtn = UIBarButtonItem(title: "关闭", style: .plain, target: self, action: #selector(onClickClose))
navigationItem.leftBarButtonItem = leftCloseBtn
}
@objc private func onClickClose() {
self.dismiss(animated: true, completion: nil)
}
override func populate(_ builder: FormBuilder) {
builder += SectionHeaderTitleFormItem().title("Web开发环境")
builder += enabledSwitch
builder += projectTextField
builder += serverTextField
}
}
WebManager.kt
class WebManager {
...
public let settings = UserDefaults(suiteName: "WebDev")!
...
// 根据id和page获取正式的url
func getWebUrl(id: String, page: String) -> String {
// 如果环境打开了
if settings.bool(forKey: "enabled"),
let server = settings.string(forKey: "server"),
let project = settings.string(forKey: "project"),
project == id
{
return "http://\(server)/\(project)/dev/\(page)"
}
let version = versionDict[id] ?? "1"
return "\(WebConst.WEB_BASE_URL)\(id)/\(version)/\(page)"
}
}
最终代码结构
运行结果
模拟器激活摇一摇,真实设备就用手摇:
查看日志:
::: tip 注意
配置好的是本地的一个服务器地址和weather
项目,所以进weather
时加载的是开发环境的链接
:::
扩展阅读
前端开发环境配置
weather
项目的vue.config.js
const packageJSON = require("./package.json");
let version = packageJSON.deploy.version;
let publicBasePath = "/book-to-be-big-fe-deploy/";
// dev环境改变version和publicBasePath以适配开发环境的链接地址
if (process.env.NODE_ENV === "development") {
version = "dev";
publicBasePath = "/";
}
module.exports = {
devServer: {
host: "0.0.0.0",
port: 8083
},
publicPath: publicBasePath + packageJSON.name + "/" + version + "/",
outputDir: "dist/" + packageJSON.name + "/" + version + "/"
};
开发环境完成,其他项目配置做法一样,甚至可以出一个 vue 项目模板