在整合基於create-react-app建立的react項目和electron時,遇到一個問題:在開發模式,能夠正常加載圖片,但執行electron-packager . 命令把項目打包成exe文件後,圖片沒法加載,控制檯報錯提示 NOT_FOUND,加載的圖片根路徑是系統盤根目錄,而代碼中是相對路徑,按道理來講,根路徑應該是項目根目錄。
控制檯提示以下:
![]()
先介紹我最終使用的解決方法:
第一步:執行npm run eject,css
yarn eject
yarn run v1.17.3
$ react-scripts eject
NOTE: Create React App 2+ supports TypeScript, Sass, CSS Modules and more without ejecting: https://reactjs.org/blog/2018...
? Are you sure you want to eject? This action is permanent. (y/N) y
執行完後從新啓動項目,失敗,此時報錯以下:html
[0] Failed to compile.
[0]
[0] ./src/index.js
[0] Error: [BABEL] F:Reactelectronreact-material-dashboardsrcindex.js: Cannot find module '@babel/plugin-syntax-jsx' (While processing: "F:\React\electron\react-material-dashboard\node_modules\babel-preset-react-app\index.js$1$0")
[0] at Array.reduce (<anonymous>)
須要刪掉node_module文件從新安裝依賴,再次啓動,啓動成功。node
第二步:修改配置文件config/webpack.config.js,在module.rules數組中,圖片加載規則處添加isEnvDevelopment && ,讓該規則只做用於開發模式下:react
oneOf: [ // "url" loader works like "file" loader except that it embeds assets // smaller than specified limit in bytes as data URLs to avoid requests. // A missing `test` is equivalent to a match. isEnvDevelopment && { test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], loader: require.resolve('url-loader'), options: { limit: 10000, name: 'static/media/[name].[hash:8].[ext]', }, },
跟問題類似的issue有:https://github.com/electron-r...
這個issue中,做者描述的問題跟我遇到的如出一轍,
根據第一個答案,須要刪除webpack.config.production.js中 {test.... loader:'url-loader'},
create-react-app隱藏了webpack配置的詳細信息,因此先經過執行npm run eject暴露webpack配置,
在webpack.config.js找到相同的配置:
刪除這兩行代碼,從新打包,圖片能夠正常加載。
猜想問題多是url-loader引發的,那麼url-loader是幹什麼的呢?
參考這篇文章:webpack file-loader和url-loader的區別webpack
file-loader能夠解析項目中的url引入(不只限於css),根據咱們的配置,將圖片拷貝到相應的路徑,再根據咱們的配置,修改打包後文件引用路徑,使之指向正確的文件。若是圖片較多,會發不少http請求,會下降頁面性能。這個問題能夠經過url-loader解決。url-loader會將引入的圖片編碼,生成dataURl。至關於把圖片數據翻譯成一串字符。再把這串字符打包到文件中,最終只須要引入這個文件就能訪問圖片了。固然,若是圖片較大,編碼會消耗性能。所以url-loader提供了一個limit參數,小於limit字節的文件會被轉爲DataURl,大於limit的還會使用file-loader進行copy。url-loader和file-loader是什麼關係呢?簡答地說,url-loader封裝了file-loader。url-loader不依賴於file-loader,即便用url-loader時,只須要安裝url-loader便可,不須要安裝file-loader,由於url-loader內置了file-loader。經過上面的介紹,咱們能夠看到,url-loader工做分兩種狀況:1.文件大小小於limit參數,url-loader將會把文件轉爲DataURL;2.文件大小大於limit,url-loader會調用file-loader進行處理,參數也會直接傳給file-loader。所以咱們只須要安裝url-loader便可。git
發起http請求。。。url-loader會將引入的圖片編碼,衆所周知,electron打包後,訪問文件是經過file協議,而不是http協議,至此,問題根源定位到了。
那麼解決方法應該是放棄使用url-loader加載圖片,而直接用file-loader就能夠了。
但我又但願在開發時,保持本來的url-loader不變,因此webpack.config.js中圖片加載的規則改爲github
oneOf: [ // "url" loader works like "file" loader except that it embeds assets // smaller than specified limit in bytes as data URLs to avoid requests. // A missing `test` is equivalent to a match. isEnvDevelopment && { test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], loader: require.resolve('url-loader'), options: { limit: 10000, name: 'static/media/[name].[hash:8].[ext]', }, },
還有另外一種不須要執行npm run eject命令的方法:經過安裝react-app-rewired模塊來更改項目的webpack配置。另外,安裝customize-cra模塊簡化配置項。
方法具體步驟:
一、安裝模塊yarn add react-app-rewired customize-cra
web
二、修改package.json文件npm
/* package.json */ "scripts": { - "start": "react-scripts start", + "start": "react-app-rewired start", - "build": "react-scripts build", + "build": "react-app-rewired build", - "test": "react-scripts test", + "test": "react-app-rewired test", }
三、在項目根目錄下添加config-overrides.js文件,添加如下內容:json
const { override,addLessLoader } = require('customize-cra'); //更改打包是圖片加載模式,解決electron打包後圖片沒法加載問題 const customizeImageLoader = () => config => { config.module.rules[2].oneOf.push({ test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], loader: 'file-loader' }); return config; } module.exports = override( customizeImageLoader() );
這種方法的缺點是:
多安裝了兩個模塊:react-app-rewired和customize-cra
相較於 npm run eject 暴露配置文件的方法,這種方法不具備透明度的,後面維護的難度較大,