背景
在嘗試讓 ChatGPT 自動開發一個桌面壁紙更改的功能時,發現引入了一個 wallpaper 庫,這個庫的入口文件是 index.js,但是 package.json 文件下的 type:"module",這樣造成了無論你使用 import from 還是 require,都會報 ES Module 引入錯誤,針對于這個問題,讓 GPT 給了很多方案,但是都沒有解決實質問題,最終,經過多次測試,發現必須借助打包工具 webpack 才能搞定這個事情。
案例代碼
node version:16
這個是用的wallpaper庫,這個庫有bug,雙屏幕失效
simple-electron-demo: 從一個簡單的electron初始庫開始從零解說electron的運行過程 - Gitee.com
另外在B站上看到一個視頻也是搞壁紙的,對方的代碼無法運行 node:18 作者也沒修復,里面看用的koffi 調用一個dll,這個dll估計是作者自己打的動態連接庫,但是這個沒有地方可以控制伸縮,代碼也放在這里
simple-electron-demo: 從一個簡單的electron初始庫開始從零解說electron的運行過程 - Gitee.com
B站視頻連接(作者堆了一堆buffer,然后把代碼搞到build報錯,實際上一個前端開發真沒必要用typescript和vue3這些東西,尤其是vite,給開發帶不來任何效率提升,卻外加了很多不必要學習的知識,就是前端內卷的一種方式吧)
Vue3+electron實現桌面壁紙更換2.0版本(已完成macOS靜態壁紙更換,后續功能開發中)_嗶哩嗶哩_bilibili
Electron 官網對 ES Module 的建議
Electron中的 ES 模塊 (ESM) | Electron
沒有看太懂,大概就是必須開啟 type:"module"
,然后引入的 js 必須是.mjs
后綴,否則就會報錯,另外大家就是講了在哪些情況,你開了 module 就會導致渲染進程無法訪問 node_modules 中的文件,也無法訪問 node api 接口
一個 ES Module 庫:wallpaper
它的入口文件是 index.js 而 package.json 中 type 設為 module,這就使得引入這個庫的 wallpaper 也得支持 type:"module",否則無法使用這個庫,一般像 vue,都會給兩個字段,一個是 main,一個是 module,以任意一種項目選擇性引入
那么 ES Module 怎樣才能正常使用?
-
webpack 打包后的代碼一般我們從來都不會遇到這種 ES Module 的問題,原因是 webpack 打包會把所有的代碼都進行預編譯整合,也即將代碼從 node_module 拷貝出來,然后再經過 babel 等的轉化,塞入打包后的代碼里,最后統一用 require 的方式進行引入
-
而基于 electron 的開發,所有的 js 都可以取自本地,因為基于 commonJS 協議的方式更符合開發本地開發方式,因此 Webpack 可以把一些代碼不打包進去,直接保留 require("vue") 引入方式,這樣不但降低了最終打包文件的體積大小,還能動態的引入所需的代碼,整體性能就很高
-
所以白名單這里就是不讓 webpack 打包,默認整個生產依賴都要打包進去
-
但是 wallpaper 默認是 ES Module 就必須轉化成 CommonJS 形式,于是就把代碼進行預編譯,然后塞到 main.js 中去,這樣 wallpaper 整個源碼就被構建進去了,也就不存在原來 type:"module"引入的概念
總結
-
webpack打包 electron 都是基于 CommonJS 方式,使用的是 require 來引入
-
如果遇到 ES Module 模塊,則將其加入到 whiteListModules 列表中,直接打包到 webpack 里面即可
-
其他沒有什么好辦法,能讓 electron 既支持 CommonJS 又支持 ES Module,兩者天然沖突
-
也沒有必要去理解這方面的問題,因為大部分情況,都被 webpack 搞定了
-
除非你自己想從零構建一個純粹的 ES Module 項目,但是只要你給別人用,或者引用別人的代碼,那么要改后綴名為.cjs,目前我覺得你是得頭大的
-
無論是源碼用了多少 import from 的寫法,webpack 最終都是給你整合成 require,fetch 的方式來搞事情