Build a Chrome Extension with Figwheel Main

Build a Chrome Extension with Figwheel Main

Bring a smooth experience to the development of Chrome Extension.

Before starting

Several years ago, I developed a chrome extension with ClojureScript, which was named GitHub Colorful Contributions .

That was the first time I have used lein-figwheel , a tool that can give you an extremely smooth live hot reloading in development.

I am deeply attracted by it. It also has great info feedback (Tips for successful reload) and a built-in ClojureScript REPL (Use repl to send the code to the browser). If you come from other languages (Not Clojure and ClojureScript), I believe you will like everything that lein-figwheel brings you very much.

Below is the screenshot from lein-figwheel README, It can reflect the great info feedback just mentioned:

Figwheel heads up example

Back to the topic, in this post, we are going to use Figwheel Main , a brand new upgraded version of lein-figwheel, to build a chrome extension. I have used it in GitHub Colorful Contributions to replace lein-figwheel. There will be some differences from regular web development that require our special attention. But don’t worry, I will point out them later.

Let’s start.

Setup

Assuming you have lein installed, then open https://rigsomelight.com/figwheel-main-template/ and copy the new command to your shell:

lein new figwheel-main hello-world.core -- --reagent

Note: for a simple setup, we won’t use +npm-bundle in the options but use cljsjs packages.

This command will create a dir named hello-world.core and add a minimal Reagent application into it.

Then we can run:

lein fig:build

to bootstrap the dev environment. After build, a new tab will be opened automatically and the repl will also be launched.

We can test it by running below in repl:

(js/alert "Am I connected?")

If you see an alert opened, then our preparations are complete.

Extension manifest

To develop a chrome extension, we need to create a manifest.json in the resources/public dir:

touch resources/public/manifest.json

You can view Manifest file format for more details. This time we will fill in the content below:

{
  "name": "Hello World",
  "version": "0.1.0",
  "manifest_version": 2,
  "browser_action": {
    "default_popup": "index.html"
  }
}

Then we can go to the next step.

Load unpacked

Now we can put it into extensions, open chrome://extensions, and click Load unpacked to select resources/public folder:

Load unpacked

Everything looks normal, but when you click the extension icon in the extensions bar, some errors will occur:

Errors

This is the first point we need to pay attention to: Chrome Apps Content Security Policy .

Since we are in a development environment, Figwheel Main will insert some inline scripts (related to its functionality) into the document. You can view the dev-main.js:

if (typeof goog == 'undefined') document.write('<script src="/cljs-out/dev/goog/base.js"></script>')
document.write('<script src="/cljs-out/dev/goog/deps.js"></script>')
document.write('<script src="/cljs-out/dev/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("figwheel.core");</script>')
document.write('<script>goog.require("figwheel.main");</script>')
document.write('<script>goog.require("figwheel.repl.preload");</script>')
document.write('<script>goog.require("devtools.preload");</script>')
document.write('<script>goog.require("figwheel.main.system_exit");</script>')
document.write('<script>goog.require("figwheel.main.css_reload");</script>')
document.write('<script>goog.require("process.env");</script>')
document.write('<script>goog.require("hello_world.core");</script>')

This violates this rule:

You can’t use inline scripting in your Chrome App pages. The restriction bans both <script> blocks and event handlers (<button onclick="…">).

Refer to the errors above, to solve this problem, we need to set the content_security_policy field in the manifest.json:

{
  "content_security_policy": "script-src 'self' 'unsafe-eval' 'sha256-xxx' 'sha256-xxx' 'sha256-xxx'; object-src 'self'"
}

The errors contain all sha256-xxx which need to be filled in the policy field. This is a little bit cumbersome. You may wonder why we can’t use the unsafe-inline? Because chrome ignores this keyword especially, even the errors tell you can 😢.

After finishing this, edit the code and you will see that your code has completed the hot reload 😎.

Production

After you finish your application, you still need to do something before bundling it.

To develop the chrome extension, you need to use chrome API to do some things, like save and sync the user storage, etc. We need to tell the closure compiler chrome is the externs we used.

There are two files we need to download:

Put them into externs folder and edit dev.cljs.edn like below content:

{:main hello-world.core
 :externs ["externs/chrome.js" "externs/chrome_extensions.js"]}

Then run:

lein fig:min

to build the production code.

Conclusion

These are all steps to build a chrome extension with Figwheel Main.

If you are looking for a real-world example as a reference, the GitHub Colorful Contributions is what you want.

Thanks for reading. Happy coding with Figwheel Main!

References:

关于我

这里是「跨老大」官方博客,唯一域名:kualaoda.com。

我是 Andy,「跨老大」项目的创始人,长期专注于跨境电商与 AI 工具的实战方法论。这里聚焦高效、可落地的教程与案例,帮助你快速上手、用对工具,真正实现降本增效。

联系方式
  • 微信:跨老大(ID: kualaoda)
  • 视频号:跨老大(名字唯一)
  • 抖音:跨老大(ID: kualaoda)
  • 快手:跨老大(ID: kualaoda)
  • 小红书:跨老大(ID: kualaoda)

以上为官方渠道,无其他联系方式。欢迎关注获取最新工具清单与实战案例,也欢迎通过私信交流使用体验与需求建议。请警惕假冒账号。

我们的使命

让 AI 成为每位跨境电商从业者的实战助手

精选真正有效的 AI 工具,提供可落地的方法论,以场景驱动、实用为先,帮助你持续降本增效。

免责说明

我们分享的工具、方法与教程仅用于合法、合规的业务场景,旨在帮助跨境电商从业者提升效率并控制合规成本。

  • 严禁将任何内容用于违法违规或侵权用途(包括但不限于攻击、欺诈、数据滥用、侵犯他人权益等)。
  • 使用者应自行审查并遵守所在国家/地区的法律法规、平台政策与数据隐私规则;涉及第三方数据或平台操作时,须事先取得合法授权与必要许可。
  • 因不当或违规使用产生的任何责任、损失、处罚或索赔,均由使用者自行承担,与本站、作者及其关联团队或公司无关。

本网站及作者不提供法律或合规意见,文档与教程仅供学习参考;如需在特殊或敏感场景中应用,请先咨询专业法律顾问。