Teach you how to implement a uTools toolbox that supports plug-in (1)

Teach you how to implement a uTools toolbox that supports plug-in (1)


For front-end students, we will often use various small tools, such as: image bed, color picking, QR code generator, url management, text comparison, json formatting. Of course, we can manage all kinds of online gadgets in chrome favorites, but as a pursuing front-end, we not only need to use it ourselves, but also can use some useful tools for the team to improve the team's research and development efficiency.

Therefore, based on the appeal, the market or many companies will make some client tools to meet the needs of their own teams, most of which are based on

to realise. But if this article only describes how to pass
To make a tool set, it will be smaller and the layout will be smaller! To be bigger, we are not only empowering the front-end, we also need to empower the back-end, testing, UI, products and even the boss . So once it gets bigger, the toolbox will become very bloated, and the size will become bigger and bigger. Everyone must upgrade every time to experience the new features. For the above problems, we need to design a pluggable design method, which is installed when it is used, and does not need to be installed when it is not used. The plug-in is released separately from the toolbox.

If you are also interested in such a tool, you can continue to read the implementation process. But you can directly upload the source code first:

Rubick source code


In the first step of the opening chapter, according to my previous routine, I took a good name first and took a pit. I wrote a booklet of "Visual Construction from 0", which was based on dota.

name. This time I named it
which is
. know
Skills can understand what it means, mainly because you can use whatever skills you want, pluggable. It is also very consistent with our philosophy:


Initialize the project

Here I use electron-vue to do the project scaffolding, directly follow the official website introduction, start to create a good one


# Install vue-cli and scaffolding boilerplate code npm install -g vue-cli vue init simulatedgreg/electron-vue rubick # Install dependencies and run your program cd rubick the Yarn # or install npm the Yarn RUN dev # or npm run dev copy the code

It s important to note here that due to

This thing used
The version is too low, and the official
The documentation has been updated to the latest, so if you just follow
If you refer to the official documentation, you will find that there are many unusable situations in the documentation. So try to upgrade to the latest version.

If you are a windows user and encounter problems with node-gyp, C++ library, etc. during installation, please refer to the solutions given in the official documentation .

main process and renderer process

Before development, it is necessary to understand

Process and
The relationship between the processes, what is
It will run when the project starts
The process is the main process, and a project has one and only one main process, and all system events such as creating windows must be carried out in the main process. Simply put, there is only one main process of our electron project. The execution code of the main process needs to be written in main.js, and all codes related to system events must be written here.

what is

What about the process? The most basic understanding is
The process is responsible for the page UI rendering we are familiar with. In fact, there is a blog that summarizes it very well. If you want to continue to understand it, you can check it out. Here I will quote the picture inside. This picture contains
Process and
The ability of the process.

With these basic knowledge, suppose you are right

The relevant understanding has reached a level of basic familiarity. We started to carry out development work. In the next development, I will refer to the design interaction of utools to design a step by step similar to utools

Window initialization

able to pass
To create a new window object, this time you need to build a 800 * 60 main search window, open
Adjust the window size and size:

mainWindow = new BrowserWindow({ height : 60 , useContentSize : true , width : 800 , frame : false , title : 'Rubick' , webPreferences : { webSecurity : false , enableRemoteModule : true , webviewTag : true , nodeIntegration : true } }) Copy code

Here are a few

The parameters need to be explained:

  • webSecurity if
    Initiated some cross-domain requests, webSecurity can be set to false
  • enableRemoteModule allows
    Process usage
  • webviewTag allowed
  • nodeIntegration allows use in web pages

At this point, we can see the most basic interactive window!

Developer mode

Plug-in development needs and

For joint debugging, so
Need to support the developer mode to help developers better develop plug-ins. First we build one
Basic information used to describe the plug-in:

{ "pluginName" : "Test plugin" , "author" : "muwoo" , "description" : "My first rubick plugin" , "main" : "index.html" , "version" : "0.0.2 " , "logo" : "logo.png" , "name" : "rubick-plugin-demo" , "gitUrl" : "" , "features" : [ { "code" : "hello" , "explain" : "This is a test plug-in" , "cmds" :[ "hello222" , "Hello" ] } ], "preload" : "preload.js" } Copy code
Core field description
  • name
    The name of the plugin repository, used for github dowload Peugeot
  • pluginName
    : The name of the plug-in.
  • description
    : Plug-in description, concisely explain the role of this plug-in
  • main
    : Entry file, if no entry file is defined, this plugin will become a template plugin
  • version
    : The version of the plug-in must comply with the Semver (semantic version) specification. Used for version update prompt
  • features
    : List of plug-in core functions
  • features.code
    : The identification code of a certain function of the plug-in, the code that will be passed to you when entering the plug-in, which can be used to distinguish different functions and display different UIs
  • features.cmds
    : How to enter this function, Chinese will automatically support pinyin and pinyin first letter, no need to add repeatedly

The way to develop plugins is to copy

Search box, so you need to monitor the search box
Event, used to read the content copied from the current clipboard:

onSearch ({ commit }, paylpad) { //Get the file path copied by the clipboard const fileUrl = clipboard.read( 'public.file-url' ).replace( 'file://' , '' ); //If you copy the plugin.json file if (fileUrl && value === 'plugin.json' ) { //read the json file const config = JSON .parse(fs.readFileSync(fileUrl, 'utf-8' )) ; //Generate plug-in configuration const pluginConfig = { ...config, //Record the path of index.html saver sourceFile : path.join(fileUrl, `../${config.main || 'index.html' } ` ), id : uuidv4(), //Mark as developer type : 'dev' , //read icon icon : 'image://' + path.join(fileUrl, `../${config.logo} ` ), //mark whether it is a template subType : ( () => { if (config.main) { return '' } return 'Template' ; })() }; } } Copy code

Here we have been able to copy according to

To get the most basic information of the plug-in, the next step is to display the search box:

commit( 'commonUpdate' , { options : [ { name : 'New rubick development plugin' , value : 'new-plugin' , icon : 'https : //static.91jkys.com/activity/img/b37ff555c748489f88f3adac15b76f18.png ' , desc : 'New rubick development plugin' , click : ( router ) => { commit( 'commonUpdate' , { showMain : true , selected : { key : 'plugin' , name : 'New rubick development plugin' }, current : [ 'dev' ], }); ipcRenderer.send( 'changeWindowSize-rubick' , { height : getWindowHeight(), }); router.push( '/home/dev' ) } }, { name : 'copy path' , desc : 'copy path' , value : 'copy-path' , icon : 'https : //static.91jkys.com/activity/img/ac0d4df0247345b9a84c8cd7ea3dd696.png' , click : () => { clipboard.writeText(fileUrl); commit( 'commonUpdate' , { showMain : false , selected : null , options : [], }); ipcRenderer.send( 'changeWindowSize-rubick' , { height : getWindowHeight([]), }); remote.Notification( 'Rubick Notification' , { body : 'Copy successful' }); } } ] }); Copy code

Here, when copying

When entering the search box, two options will appear directly, a new plug-in and a copy path function:

When clicked

New rubick plugin
Function, you need to jump to
Page, load the basic content of the plug-in, the only thing you need to pay attention to is
The height of the content loaded on the page should be the height of the largest rubick window. So you need to adjust the window size:

ipcRenderer.send( 'changeWindowSize-rubick' , { height : getWindowHeight(), }); Copy code


The vue code inside will not be introduced in detail here, because most of it is just a css drawing, just look at the display interface:

At this point, the developer mode is completed, and then I will introduce how to make the plug-in

Ran in.

Run the plugin

A container is required to run the plug-in, and electron provides a

Container to load external web pages. So we can use
The ability to achieve dynamic web page rendering, the so-called web page here is a plug-in. But the webpage is unavailable
Ability, and our purpose of making plug-ins is to open up and restrict, we need to open some built-in plug-ins
ability. Fortunately
provided a
The ability to preset a script to execute when the page loads.

In other words, we can write one for our own plug-in

To load. But here we need to pay attention that we must maintain the personality of the plug-in and inject the global into the plug-in
For plug-in use, so it can be loaded directly

//webview plugin.vue < webview id = "webview" :src = "path" :preload = "preload" > </webview > < script > export default { name : "index.vue" , data ( ) { return { path : `File://${ this .$route.query.sourceFile} ` , //Load preload.js in the current static directory preload : `File://${path.join(__static, './preload.js' )} ` , webview : null , query : this .$route.query, config : {}, } } } </script > copy code


We can use it like this:

if (location.href.indexOf( 'targetFile' )>- 1 ) { filePath = decodeURIComponent (getQueryVariable( 'targetFile' )); } else { filePath = location.pathname.replace( 'file://' , '' ); } window .utools = { //All api implementations of utools } //load the plug preload.js the require (path.join (filePath, '../preload.js' )); duplicated code

Now that the plug-in has been loaded, let s take a look at the effect:

Concluding remarks

This article mainly introduces how to implement a plug-in loading process similar to utools. Of course, this is far from all of utools. In the next issue, we will introduce how to implement the global plug-in of utools, such as

Screen color, screenshot, search
And other capabilities. Welcome everyone to experience Rubick. If you have any questions, you can raise an issue at any time and we will give feedback in time.

In addition, if you think the design and implementation ideas are useful to you, you are also welcome to give a Star: github.com/clouDr-f2e/...