Harmony Next 使用 L2TP IPSec PSK VPN
之前在我的 用 Docker 快速部署 PPTP VPN 和 L2TP + IPSEC VPN 一文中,我介绍了如何使用 Docker k快速署 L2TP IPSec VPN,但是在纯血鸿蒙下一直无法成功。
发现是因为无法匹配通讯加密方法。
进入容器,如下修改一下 /etc/ipsec.conf
文件的通讯加密方法,
1 | conn l2tp-psk |
之后重启服务即可,service ipsec restart
。
之前在我的 用 Docker 快速部署 PPTP VPN 和 L2TP + IPSEC VPN 一文中,我介绍了如何使用 Docker k快速署 L2TP IPSec VPN,但是在纯血鸿蒙下一直无法成功。
发现是因为无法匹配通讯加密方法。
进入容器,如下修改一下 /etc/ipsec.conf
文件的通讯加密方法,
1 | conn l2tp-psk |
之后重启服务即可,service ipsec restart
。
hclient-cli 是官方推出的一个面向无图形界面的机器的接入方案。
有这个工具的情况下,我们可以让我们远端的服务器接入到懒猫的网络中,访问懒猫上的数据资源。
官方库文档有接口的使用说明,这里就不再阐述,我提交了一个 PR,对官方的接口简单的用 bash 脚本封装了一下,减少使用过程中的输入量。同时还包含了一个构建 Docker 镜像的方案,其实就是把 cli 程序加入到镜像中。
目前我的远端服务是 Docker 容器形式运行的,因此这里分享一下 Docker 使用样例。
这里的远端应用以我的远端服务器上的青龙面板为例。
首先给出一个 Docker 容器启动命令示例:
1 | docker run -itd \ |
- 请注意不要暴露你的 7777 管理端口和 61090 代理端口给全局网络
- 容器启动后,所有 lnmp 网络中的容器可以通过
172.20.0.66:61090
代理访问懒猫资源。- 宿主机可以通过
127.0.0.1:7777
管理,通过127.0.0.1:61090
代理访问。
在宿主机中,调用 cmd.sh
(在我的那个 PR 中)完成懒猫网络的登陆。
1 | ./cmd.sh add_box |
登陆成功后,打开远端的青龙面板,安装依赖 axios
和 https-proxy-agent
。之后增加环境变量配置如下:
1 | LAZYCAT_PROXY=http://172.20.0.66:61090 |
创建一个新的测试 js 脚本如下:
1 | const axios = require('axios'); |
调试运行,成功获取到懒猫微服上的 Influxdb
中的数据。
今天发现了一个有意思的工具 —— 青龙面板。
平时经常会有一些零零碎碎的脚本需要运行,放在宿主机运行,就要安装 nodejs 的环境,如果放在 docker 里运行,就要写 Dockerfile ,太繁琐。
使用这个青龙面板,相当于直接拥有一个容器空间,自带 python, nodejs 环境。可以理解为是云服务商的那种 server less 服务。
这样我们可以把零碎的脚本放在一个独立的代码库里面,进行版本管理。
当然,如果你想要立即执行拉取任务,也提供了单独的运行按钮可以立即执行。
独立的依赖管理面板,可以只需要安装一次依赖,就可以所有脚本都使用。
这是拉取下来的代码,可以在线编辑。
这是调试界面,可以实时调试。
编辑好的脚本,可以在这里设置计划任务,让脚本按计划运行。
在 React 中,useEffect 的依赖项决定了其什么时候执行。
useEffect 接受两个参数:
1 | useEffect(() => { |
1.无依赖项数组(每次渲染都会执行): 如果不传入依赖项数组,useEffect 中的副作用函数将在每次组件渲染后都执行。
1 | useEffect(() => { |
场景:这种用法不常见,通常用于希望在每次渲染时执行某些逻辑,但要注意性能开销。
2.空依赖项数组(只在组件挂载和卸载时执行): 如果传入一个空数组 [],则 useEffect 只会在组件挂载时运行一次,并在组件卸载时运行清理函数(如果提供了)。
1 | useEffect(() => { |
场景:通常用于初始化数据(例如组件挂载时的 API 请求),或在组件卸载时执行清理操作(例如清理定时器、取消订阅等)。
3.具有依赖项的数组(依赖项变化时执行): 当传入特定的依赖项时,useEffect 只有在这些依赖项的值发生变化时才会重新执行。
1 | useEffect(() => { |
场景:用于根据某个特定状态或 prop 变化来执行副作用逻辑。例如,当 count 变化时,可能需要重新获取某些数据或触发其他副作用。
4.多个依赖项: 可以在依赖项数组中传入多个依赖项,useEffect 将会在其中任何一个依赖发生变化时重新执行。
1 | useEffect(() => { |
场景:用于当多个状态或 prop 变化时,重新执行某个逻辑。例如,可能需要在 count 或 user 变化时重新发起某个 API 请求。
1.依赖项的选择要遵循以下原则:
2.常见的误区与优化:
ET碎碎念,每周更新,欢迎订阅,点赞,转发!
Steemit 的几个前端项目(condenser, wallet, faucet)都使用了 redux 和 redux-saga。
这次升级 faucet 所有依赖库,发现新版本 redux 推荐使用官方的 @reduxjs/toolkit
工具集来实现 redux 的功能。
既然 redux 的官方推荐使用工具集,那么这次升级我们也要相对应的把原有的 redux 相关代码做改动。
其中,为了应对复杂的异步请求而引入的 redux-saga
,我不是很确定是否与工具集兼容,因此投入了时间来研究了一下。
redux-saga
与 @reduxjs/toolkit
一起使用创建 Redux Store: @reduxjs/toolkit
提供了 configureStore
来简化 store
的创建过程。你可以将 redux-saga
中间件添加到 store
中。
创建并运行 Saga 中间件: 使用 redux-saga
的 createSagaMiddleware
来创建 saga
中间件,然后将其添加到 configureStore
中。
运行你的 Saga
: 在 configureStore
创建 store
后,使用 sagaMiddleware.run
来启动你的 saga
。
下面是简单的例子。
store.js 文件
1 | // store.js |
saga.js 文件
1 | // sagas.js |
ET碎碎念,每周更新,欢迎订阅,点赞,转发!
由于 faucet 项目全部是手动搭建的环境,所以在把 react15 升级到 react18 后,
1 | import { createRoot } from 'react-dom/client'; |
使用上面的代码测试环境是否搭建成功的时候,报 React is not defined
错误。
原因是:在 React 18 中,虽然可以使用 createRoot
来渲染组件,
但仍然需要显式地导入 React 以支持 JSX 语法。
在 JSX 中,<h1>Hello, world</h1>
会被编译成 React.createElement('h1', null, 'Hello, world')
。
因此,即使你没有直接使用 React,它仍然需要被导入。
由于 babel
我也升级到最新了,在 7.9 版本后,可以使用 @babel/preset-react
来自动引入 JSX 转换。
而不用去显式的导入 React 了。
具体方法就是在 babel.config.js
中对 @babel/preset-react
增加配置如下:
1 | { |
如此设置后,再次编译执行,报错就没有了。
ET碎碎念,每周更新,欢迎订阅,点赞,转发!
在 React 18 中,createStore
是 Redux
提供的一个函数,用于创建 Redux store
,但从 Redux Toolkit v5
开始,createStore
已被标记为弃用,并建议使用 configureStore
作为替代。
configureStore
是 Redux Toolkit
中提供的一个函数,它简化了 Redux
的配置过程,内置了 Redux DevTools
、默认的中间件配置等。
下面是如何使用 configureStore
替代 createStore
的一个简单示例:
1 | import { configureStore } from '@reduxjs/toolkit'; |
这次重构 faucet 将会替换掉 createStore
方法。
Redux、React-Redux 和 Redux-Saga 是前端开发中常用的状态管理和异步数据处理工具。它们各自有不同的功能和用途。
Redux 是一个用于 JavaScript 应用的状态管理库。它提供了一种可预测的方式来管理应用的全局状态。
React-Redux 是官方提供的 Redux 和 React 的绑定库。它允许 React 组件与 Redux store 进行连接,使得组件能够访问 Redux 的状态并分发 actions。
<Provider>
组件: 这个组件将 Redux store 提供给应用内所有的组件。1 | import { Provider } from 'react-redux'; |
1 | import React from 'react'; |
Redux-Saga 是一个用于处理 Redux 应用中的异步操作的中间件。它基于 ES6 的 Generator 函数,使得处理复杂的异步逻辑(如异步 API 请求、并发请求、失败重试等)变得更直观和可管理。
1 | import { call, put, takeEvery } from 'redux-saga/effects'; |
这三个工具通常配合使用,以实现复杂的状态管理和异步数据处理。
ET碎碎念,每周更新,欢迎订阅,点赞,转发!
最近在弄faucet 的重构工作,因为要全面使用新的依赖和模式,遇到了很多问题。
比如最近一周一直被 jest 无法在 ESM 模式下工作的问题卡住。
搜索引擎 + chatgpt 多方面的尝试都没有找到有效方案。
直到昨天看到 jest 官方文档里有专门的一页说这个,才搞定问题。
解决方案就是两步。
第一步是用空配置 {}
替换掉之前的 jest.config.js
中 transform
,即关闭 transform
。
第二步增加环境变量 --experimental-vm-modules
,以启用 node 的实验 API,因为 jest 使用的 node 的实验 API 实现的 ESM 支持,这也就意味着,可以卸载掉 babel-jest
插件了。
启用实验 API 这里, jest 官方文档只给了两个 CLI 下的使用例子,而我们的项目使用的是 package.json
中的 scripts
方式。
因此要想在 scripts
里启用,可以按照下面的格式:
1 | "scripts": { |
每次看完用完,因为别的项目又切换到非 js 语言,过段时间就又忘了,所以写下来总结一下,要不然每次都要现搜索。
是的,在 ESM 模式下,使用 import 时需要包含文件的扩展名。
这是因为 ESM 模块解析严格遵循文件路径规范,不像 CommonJS 那样自动推断 .js、.json 或 .mjs 等扩展名。
假设有下面的文件结构
1 | project/ |
在 app.js 中,你需要这样导入 helper.js
:
1 | import { myHelperFunction } from './utils/helper.js'; |
在 JavaScript 中,import 语句的语法有两种主要形式:具名导入和默认导入。
加 {} 和不加 {} 的区别在于你是导入模块中的一个具名导出还是默认导出。
1 | // utils.js |
1 | // utils.js |
这里对我来说,如果不看文档,纯靠我自己的经验
我一直以为不加 {} 的时候,是把整个文件导出的
也就是按照例子的代码,我的直观感觉应该是myFunc.myFunction()