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)

Preface

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

electron
to realise. But if this article only describes how to pass
electron
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

Named

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.

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

achieve

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

electron
project:

# 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

electron-vue
This thing used
electron
The version is too low, and the official
electron
The documentation has been updated to the latest, so if you just follow
electron-vue
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

electron
of
main
Process and
renderer
The relationship between the processes, what is
main
process:
electron
It will run when the project starts
main.js
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

renderer
What about the process? The most basic understanding is
Renderer
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
main
Process and
renderer
The ability of the process.

With these basic knowledge, suppose you are right

electron
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
electron
Toolbox.

Window initialization

electron
able to pass
BrowserWindow
To create a new window object, this time you need to build a 800 * 60 main search window, open
main.js
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

webPreferences
The parameters need to be explained:

  • webSecurity if
    BrowserWindow
    Initiated some cross-domain requests, webSecurity can be set to false
  • enableRemoteModule allows
    renderer
    Process usage
    remote
    Module
  • webviewTag allowed
    webview
    label
  • nodeIntegration allows use in web pages
    node

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

Developer mode

Plug-in development needs and

rubick
For joint debugging, so
rubick
Need to support the developer mode to help developers better develop plug-ins. First we build one
plugin.json
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

plugin.json
Into
rubick
Search box, so you need to monitor the search box
change
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

plugin.json
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

plugin.json
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
home
Page, load the basic content of the plug-in, the only thing you need to pay attention to is
home
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

on

renderer
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

rubick
Ran in.

Run the plugin

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

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

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

preload.js
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
API
For plug-in use, so it can be loaded directly
rubick
Built-in
preload.js
,
preload.js
Personalized
preload.js
:

//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

for

preload.js
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/...