There seems to be an OpenBuild community ecological project that has been stalled for a while. The initiator wants to continue pushing it forward quickly, but there hasn't been much progress, and it's hard to find other suitable people—there's no choice but for me to take it over.
The goal of this project is to develop a plugin for the open-source Q&A platform Answer that supports logging in with a Web3 wallet. From the functionality to be implemented, this should be a small project, with development and front-end and back-end integration estimated to take about 1.5 to 3 person-days.
However, reality hit me hard...
Requirement Analysis#
From the official plugin development documentation, it seems that what needs to be done is a "connector-backend plugin."
With this premise, I roughly understood the code of several existing connectors and found that each plugin can only specify one type, and backend plugins cannot directly support UI; they all redirect to an external authorization URL.
However, there is no ready-made external authorization URL for Web3 wallet login, so to meet the requirements, it may be necessary to write a matching "router-standard UI plugin" and develop a page:
- Display a connect wallet button;
- After connecting the wallet, the user signs;
- Get nonce from the backend, with the front end passing in the wallet address;
- The front end invokes the wallet for the user to sign;
- After signing, call the backend authorization interface, with the front end passing in the user's signature information, wallet address, etc.;
- After a successful request, return to the main interface.
The parts of the text above that are bolded require data interaction with the backend, meaning there need to be two backend interfaces.
The process looks simple, right? And it really is quite simple!
Development Process#
The backend part was mostly completed a few months ago, and it was basically just the front-end interface and integration that were missing.
Since this project does not separate the front and back ends, if I want to run it completely, based on the information from the official documentation, I would need to install Docker, a database, etc.
However, I hadn't installed these locally before, and I currently have no plans for other projects that require them, so it wouldn't make sense to install software that I would hardly use just to save precious storage space on my computer.
So, I first adopted a pure front-end approach to develop the layout, styles, and functionality of the interface, even if the backend interface requests failed; including the time spent reading documentation and familiarizing myself with the basic mechanisms of the plugin, it took about 1 person-day to complete.
I scheduled a day on the weekend with the person responsible for the backend to focus on integration, hoping to finalize the delivery, but faced continuous setbacks...
Because I hadn't installed and set up the backend environment locally, I couldn't follow the normal plugin loading and running process, and some issues had not been encountered during the development phase; when I asked my backend colleague to download my code and run the entire process, all sorts of "strange" problems popped up...
At first, whenever there was a front-end issue, I initiated a video conference to see how he was operating, and I guided him to solve it—after a few times, I suddenly realized, isn't this the legendary "pair programming"? 😂😂😂
Later, I thought to myself, "This isn't going to work; it's just too inefficient!"
In the end, I tried to put aside my reservations and let him guide me on how to get the backend running, so I could test and adjust the front-end code myself.
After being guided, I found that I really only needed to install Go, and I could directly use the SQLite that comes with macOS for the database, without needing to deal with Docker— I really should have let him be my "navigator" from the start!
Although things didn't go smoothly afterward, we no longer needed to hold video meetings; if there was an issue, we just needed to send a screenshot and a brief description via WeChat, greatly improving efficiency!
While testing the plugin I developed, I also discovered a bug in the plugin loading mechanism, so I fixed it and submitted a PR, achieving an extra +1! 😁😁😁
After a day or two of wrapping things up, the plugin we developed was delivered, and under the guidance and suggestions of the official reviewers, we merged the original two plugins into one—on the surface, it is a "router-standard UI plugin," but in essence, it is also a "connector-backend plugin."
Thus, we resolved the "constipation" issue in these three to five days—let's celebrate! 🎉🎉🎉
Pitfall Experience#
This development was based on the main project version 1.4.0, and the imperfections in the official documentation and plugin system, along with my somewhat awkward mindset, led me to stumble into some pitfalls. Below, I will share some key points for local debugging aimed at front-end developers to help avoid detours!
First, for those who are sensitive like me, I want to emphasize again—you only need to install Go, and you can use the SQLite that comes with macOS for the database!
Taking our developed plugin as an example, let's assume the plugin name is connector-wallet
—
Backend Environment#
Ensure that the plugin package is imported in the main project’s cmd/answer/main.go
, even if it currently does not exist:
import (
answercmd "github.com/apache/incubator-answer/cmd"
_ "github.com/apache/incubator-answer-plugins/connector-wallet"
)
Whether it is a pure front-end plugin or a "superficially front-end plugin," during debugging, the code generated by the template should be placed in the ui/src/plugins
folder, and a go.work
file should be created in the root folder:
go 1.22.0
toolchain go1.23.2
use (
.
./ui/src/plugins/connector-wallet
)
Execute make ui
to build the front-end code, then use go build -o answer ./cmd/answer/main.go
to compile the backend code, which will generate the answer
file, and all subsequent operations will use it.
Execute ./answer init -C ./answer-data/
to initialize the system, and you need to visit http://localhost
in the browser to fill in the information, where you should select SQLite for the database and replace /data
with the absolute path of the answer-data
folder.
Execute ./answer run -C ./answer-data/
to start the backend service, and visit http://localhost
again to log in with the initial account and enable the plugin you want to debug in the backend!
Finally, change REACT_APP_API_URL
in ui/.env.development
to http://localhost:80/
to start the front-end development server to access the backend interface.
Frontend Environment#
After installing the dependencies, you need to delete several folders under the plugin folder to avoid issues:
- Delete the
dist
folder and themain
,module
,types
, andexports
fields inpackage.json
; otherwise, the page will render the compiled files, and changes to the source files will not trigger a refresh; - Delete
node_modules
; otherwise, the i18n configuration read by the plugin will not be from the main project, which may be due toreact-i18next
not using a singleton pattern at the underlying level, resulting in two configurations.
Publishing the Plugin#
If additional dependencies are added to the front-end plugin, you need to modify the configuration in vite.config.ts
of the plugin package:
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js';
export default defineConfig({
plugins: [
...,
cssInjectedByJsPlugin(), // Must be included when there are style files, otherwise styles will be messed up
...,
],
build: {
...,
rollupOptions: {
external: [
..., // Declare your additional dependencies
],
output: {
globals: {
..., // Declare your additional dependencies
},
},
},
},
});
Conclusion#
Thanks to OpenBuild for providing this opportunity. Although I was initially reluctant to take it on because I thought I had more important and prioritized things to do... but if you squeeze time, there will still be some!
Thanks to my backend colleagues for their active cooperation, allowing us to solve this "constipation" problem that had been dragging on for months together!
Thanks to the reviewers from Answer for accompanying me in practicing English in the PR, setting a good start for my future international development!
Although I had previously submitted PRs to several other open-source projects, they were mostly minor fixes, and there was hardly any communication before they were merged directly; contributing to Answer gave me a real sense of doing open source!
Salute to all OPEN SOURCERORs!!!
Other reading addresses for this article: Personal Website|WeChat Official Account