在整合基于create-react-app创建的react项目和electron时,遇到一个问题:在开发模式,可以正常加载图片,但执行electron-packager . 命令把项目打包成exe文件后,图片无法加载,控制台报错提示 NOT_FOUND,加载的图片根路径是系统盘根目录,而代码中是相对路径,按道理来说,根路径应该是项目根目录。
控制台提示如下:
先介绍我最终使用的解决方法:
第一步:执行npm run eject,
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
执行完后重新启动项目,失败,此时报错如下:
[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文件重新安装依赖,再次启动,启动成功。
第二步:修改配置文件config/webpack.config.js,在module.rules数组中,图片加载规则处添加isEnvDevelopment && ,让该规则只作用于开发模式下:
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的区别
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即可。
发起http请求。。。url-loader会将引入的图片编码,众所周知,electron打包后,访问文件是通过file协议,而不是http协议,至此,问题根源定位到了。
那么解决方法应该是放弃使用url-loader加载图片,而直接用file-loader就可以了。
但我又希望在开发时,保持原本的url-loader不变,所以webpack.config.js中图片加载的规则改成
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模块简化配置项。
方法具体步骤:
1、安装模块yarn add react-app-rewired customize-cra
2、修改package.json文件
/* 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",
}
3、在项目根目录下添加config-overrides.js文件,添加以下内容:
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 暴露配置文件的方法,这种方法不具有透明度的,后面维护的难度较大,
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。