当前位置:网站首页>The process and harvest of developing browser plug-ins with clojurescript
The process and harvest of developing browser plug-ins with clojurescript
2022-07-26 16:15:00 【Flying watermelon】
There are many links in this article , Click this article https://liujiacai.net/blog/2017/11/22/create-firefox-chrome-extensions-in-clojurescript/ Go to personal blog to browse .
With Firefox 57 The arrival of the , A browser plug-in previously maintained gooreplacer Must upgrade to WebExtensions To continue to use , Read what I wrote before JS Code , There is no impulse to change , Afraid to change this place , That place suddenly broken 了 . therefore , This time cljs, On the whole, the process is very smooth , In addition to the functions before migration , Added more functions , Hope to become the simplest and easiest redirection plug-in :-)
Gossip , The following contents will be introduced in turn cljs How it works 、 development environment , How to make cljs Adapter browser plug-in specification , And rewrite gooreplacer Some experience when . Readers of this article need to be aware of Clojure Language 、 Have a basic understanding of the general process of browser plug-in development , And complete ClojureScript Of Quick Start. about Clojure, I'm in at the moment sf There is a set of video courses , For reference .
For the convenience of everyone cljs Developing a plug-in , I sorted out a template , For your reference .gooreplacer The full code is here , The technology stack is ClojureScript + Reagent + Antd + React-Bootstrap.
ClojureScript Working mechanism
ClojureScript It's using Clojure To write , The final compilation generates JS A compiler for code , Use during compilation Google Closure Compiler To optimize JS Code 、 Solve the problem of modular references . The overall workflow is as follows :
Cljs Also provide With native JS Interaction 、 Integrate the support of third-party class libraries , therefore , As long as you can use JS The place of , Can be used cljs,
Development environment preparation
Development cljs Preferred environment lein + figwheel,figwheel comparison lein-cljsbuild Provides the function of hot loading , This is important for development UI Very important !
For general cljs application , Basically, they use one script Tag to reference the compiled js file , And then this js File and then load other dependencies . such as :
<html>
<body>
<script type="text/javascript" src="js/main.js"></script>
</body></html>js/main.js yes project.clj Output file specified inside , It will load other required files , The contents are as follows :
var CLOSURE_UNCOMPILED_DEFINES = {};
var CLOSURE_NO_DEPS = true;
if(typeof goog == "undefined")
document.write('<script src="js/out/goog/base.js"></script>');
document.write('<script src="js/out/goog/deps.js"></script>');
document.write('<script src="js/out/cljs_deps.js"></script>');
document.write('<script>if (typeof goog == "undefined") console.warn("ClojureScript could not load :main, did you forget to specify :asset-path?");</script>');
document.write('<script>goog.require("process.env");</script>');document.write("<script>if (typeof goog != \"undefined\") { goog.require(\"figwheel.connect.build_dev\"); }</script>");
document.write('<script>goog.require("hello_world.core");</script>');eliminate inline script
For general Web project , Just quote this one js Documents are enough , But for browser plug-ins , There are some problems , Browser plug-ins for security reasons , Is not to allow implementation incline script, The following errors will be reported
To get rid of these mistakes , Manual loading js/main.js Files dynamically imported inside ,require The required namespace is enough , The modified html as follows :
<html>
<body>
<script src="js/out/goog/base.js"></script>
<script src="js/out/cljs_deps.js"></script>
<script src="js/init.js"></script>
</body></html>among init.js The content is :
// figwheel For hot loading , there build_dev It's actually build_{build_id}, The default is dev
goog.require("figwheel.connect.build_dev");
// Load as main The namespace of
goog.require("hello_world.core");In this way, it can run normally in the browser plug-in environment . Can be in DevTools Observed in all references js file
In the lower left corner you can see , All in all 92 File .
about background page/option page/popup page This measure can be adopted in all three places , however content script Can't specify js Script loading order , One way you can think of is :
"content_scripts": [{
"matches": ["http://*/*", "https://*/*"],
"run_at": "document_end",
"js": ["content/js/out/goog/base.js", "content/js/out/cljs_deps.js", "content/init.js"]
}]there content Directory and manifest.json At the same level . In this way, the following errors will be reported
Following the error , It can be seen that it is base.js Then dynamically reference other js When you file , It starts with visiting the website as the relative path , Therefore, we can't find the right JS The file .
The solution is to set up cljsbuild Of optimizations by :whitespace, Pack all the files into one file , Then just quote this one , This method is not perfect , use whitespace On the one hand, it makes the compilation time longer , On my machine, I need 12s; On the other hand, it cannot be used figwheel, Will be submitted to the A Figwheel build must have :compiler > :optimizations default to nil or set to :none Error of , Therefore, the function of code hot loading cannot be used .
gooreplacer It only uses background page And option page, So this problem is avoided .
distinguish dev And release Pattern
there dev It refers to the normal development process ,release It refers to the completion of development , The process of preparing to package and upload to the app store .
stay dev In the process , Recommended settings cljsbuild Of optimizations by none, In order to get the fastest compilation speed ; stay release In the process , You can set it to advanced, To compress 、 Optimize js file , In order to minimize the final volume .
In order to reuse the pictures used in both modes 、css And so on , Soft chain can be used to realize ,resources The directory structure is as follows :
.
├── css
│ └── option.css
├── dev
│ ├── background
│ │ ├── index.html
│ │ └── init.js
│ ├── content
│ ├── manifest.json -> ../manifest.json
│ └── option
│ ├── css -> ../../css/
│ ├── images -> ../../images/
│ ├── index.html
│ └── init.js
├── images
│ ├── cljs.png
│ ├── cljs_16.png
│ ├── cljs_32.png
│ └── cljs_48.png
├── manifest.json
└── release
├── background
│ ├── index.html
│ └── js
│ └── main.js
├── content
│ └── js
│ └── main.js
├── manifest.json -> ../manifest.json
└── option
├── css -> ../../css/
├── images -> ../../images/
├── index.html
└── js
└── main.jssecondly , For the convenience of opening multiple figwheel Instance to compile separately background、option Inside js, Multiple defined lein Of profiles, To specify the configuration in different environments , For details, please refer to Template project.clj file .
externs
stay optimizations by advanced when ,cljs Will fully borrow Google Closure Compiler To compress 、 Obfuscated code , Will rename the variable name to a b c Such abbreviations , In order not to chrome/firefox plug-in unit API The functions inside are confused , You need to load their corresponding externs file , Generally, only these two are needed chrome_extensions.js、chrome.js.
Test environment
cljs Self contained test Function comparison rub , What works better is doo, To use it , It needs to be installed in advance phantom To provide headless Environmental Science , After writing the test, it can be executed :
lein doo phantom {build-id} {watch-mode}The great thing is that it can also support hot loading , So I keep it open during the development process .
re-agent
re-agent It's right React An encapsulation of , To conform to cljs Development habit . No exaggeration , For non professional front-end programmers , Want to use React,cljs Than jsx It's a better choice ,Hiccup-like The grammar of jsx More compact , Don't pay attention anymore webpack,babel And so on js Tools , More important immutable stay cljs Everywhere in ,re-agent There is a mechanism to maintain the state atom, There is no need to strictly distinguish React Inside props And state.
understand re-agent The best way is to start with the example given on its official website , Then read re-frame wiki Inside Creating Reagent Components, Understand three different form The difference between ,98% gooreplacer All in use form-2. If you are interested in the principle , It is suggested that other wiki After watching .
re-agent Another point is more practical , Provide for the right to React Conversion functions of native components :adapt-react-class, Very simple to use :
(def Button (reagent/adapt-react-class (aget js/ReactBootstrap "Button")))
[:div
[:h2 "A sample title"]
[Button "with a button"]]So you don't have to worry React The class library of cannot be in cljs Used in .
Speaking of re-agent, I can't help but mention om.next, These two are in the cljs The community should be the most famous React wrapper,om.next The difficulty of concept and use is much higher than re-agent, Beginners generally do not recommend using it directly om.next. Interested parties can see the comparison between the two :
- Why Re-frame instead of Om Next, as well as Reddit Discussion on
- A rant on Om Next
pit
macro
cljs The mechanism of the add in is different from Clojure, Generally, macros need to be defined in a single file , And then in cljs with (:require-macros [my.macros :as my]) Quote in this way , And the file name suffix of the macro definition must be clj or cljc, It can't be cljs, This has been troubling me for a long time ...
Due to macro compilation and cljs Programming at different times , So if the macro is written incorrectly , We need to repl Kill and restart the new macro feed to cljs, This is also painful , because repl The startup speed of is really a little slow . This is in Clojure Although it also exists , however Clojure Average inside repl If you open it, you won't close it , Until the computer restarts .
IDE
Clojure It uses Emacs + Cider Our development environment is perfect , But here we are cljs Inside , The development process is not so smooth , Always a little stumbling , Also give cider I mentioned issue, It seems that no one has paid attention , Support is really bad , But there is. figwheel, To some extent, it can make up for this defect . stay Emacs It's equipped with repl May refer to :
- https://cider.readthedocs.io/en/latest/up_and_running/#clojurescript-usage
Cider By default rhino As repl Evaluation environment , This function is very limited when developing browser plug-ins , But it is still possible to view the function definition . It can be replaced by figwheel.
summary
ClojureScript You can be Clojure A killer application of language ,React So that the back-end programmers can quickly make a beautiful and practical interface .ClojureScript + React, I can't be happy anymore !
JS The endless frameworks emerging in the community have deterred me from trying every time , With cljs, Be regarded as Lisp It extends to a broader “ territory ”. Recently I saw such a sentence , Share with you :
Maybe Lisp Not the most appropriate language to solve all problems , But it encourages you to design the most appropriate language to solve this problem .
The source forgot , Generally speaking, it means .
Reference resources
- Chrome extension in ClojureScript
- https://github.com/binaryage/chromex-sample
边栏推荐
- Pat grade a 1044 shopping in Mars
- SQL statement -- single line comment and multi line comment
- Implementation of personalized healthy diet recommendation system based on SSM
- Pat class a 1047 student list for course
- Technology vane | interpretation of cloud native technology architecture maturity model
- PAT甲级 1050 String Subtraction
- Draw a beautiful outline of the middle school playground and generate longitude and latitude data
- 13 years of senior developers share a year of learning rust experience: from the necessary bibliography to code practice
- Google Earth Engine——MERRA-2 M2T1NXAER:1980-2022年气溶胶逐日数据集
- Test cases should never be used casually, recording the thinking caused by the exception of a test case
猜你喜欢

2022 latest Beijing Construction Safety Officer simulation question bank and answers

13 years of senior developers share a year of learning rust experience: from the necessary bibliography to code practice

Delta controller rmc200

Re7:读论文 FLA/MLAC Learning to Predict Charges for Criminal Cases with Legal Basis

技术风向标 | 云原生技术架构成熟度模型解读

Google Earth engine - merra-2 m2t1nxaer: aerosol daily data set from 1980 to 2022
![[ten thousand words long text] Based on LSM tree thought Net 6.0 C # realize kV database (case version)](/img/84/640de0bf779cd45498204909be56d1.png)
[ten thousand words long text] Based on LSM tree thought Net 6.0 C # realize kV database (case version)

HaWe screw cartridge check valve RK4

2022 what is your sense of security? Volvo asked in the middle of the year

基于sisotool极点配置PI参数及基于Plecs的三相电压源逆变器仿真
随机推荐
开发日常小结(11):文件上传功能改进:中文字符检测与文本内容处理
综合设计一个OPPE主页--导航栏的设计
【万字长文】使用 LSM-Tree 思想基于.Net 6.0 C# 实现 KV 数据库(案例版)
Internet Protocol
parker电磁阀D1VW020DNYPZ5
2022年最新北京建筑安全员模拟题库及答案
Botu PLC Sequential switch function block (SCL)
《From SICP to Lisp》视频回播
Implementation of SAP ABAP daemon
[BJDCTF2020]Easy MD5
Google Earth Engine——MERRA-2 M2T1NXAER:1980-2022年气溶胶逐日数据集
HaWe screw cartridge check valve RK4
Is it safe for Guoyuan futures to open an account online? What is the account opening process?
Understand │ XSS attack, SQL injection, CSRF attack, DDoS attack, DNS hijacking
PAT甲级 1044 Shopping in Mars
Activity之onCreate、onRestoreInstanceState恢复数据的区别
Clojure Web Development -- ring user guide
Analyzing method and proc in Ruby
PAT甲级 1047 Student List for Course
我们被一个 kong 的性能 bug 折腾了一个通宵