create-react-app 和electron项目整合:解决打包后没法加载图片问题

在整合基于create-react-app建立的react项目和electron时,遇到一个问题:在开发模式,能够正常加载图片,但执行electron-packager . 命令把项目打包成exe文件后,图片没法加载,控制台报错提示 NOT_FOUND,加载的图片根路径是系统盘根目录,而代码中是相对路径,按道理来讲,根路径应该是项目根目录。
控制台提示以下:
clipboard.png

先介绍我最终使用的解决方法:
第一步:执行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 暴露配置文件的方法,这种方法不具备透明度的,后面维护的难度较大,

参考资料:
React-CRA 多页面配置(npm run eject)
customize-cra API说明

相关文章
相关标签/搜索