前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >react+electron使应用窗口相互独立

react+electron使应用窗口相互独立

作者头像
winty
发布2020-08-24 11:00:03
1.6K1
发布2020-08-24 11:00:03
举报
文章被收录于专栏:前端Q前端Q

听说99%的前端同学都来这里充电吖!

欢迎关注前端小北,我是亚北!

前两篇文章我们介绍了react+electron构建桌面应用和如何加载本地的静态资源。然后现在有个需求,是要使应用里的弹窗独立于主窗口,今天来实现这个需求。

在之前我们知道electron通过main.js这个文件里new一个BrowserWindow来新建一个窗口,同样的,这个应用的弹窗,也可以通过new一个BrowserWindow来新建:

代码语言:javascript
复制
const { app, BrowserWindow } = require('electron')

function createWindow () {   
  // 创建浏览器窗口
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true,
      webSecurity: false,
      preload: `${__dirname}/preLoad.js`
    }
  })
  // 并且为你的应用加载index.html
  win.loadURL(url.format({
   pathname: path.join(__dirname, 'dist/index.html'),
   protocol: 'file:',
   slashes: true
 }))
  // 创建第二个窗口
  const win2 = new BrowserWindow({
    width: 400,
    height: 300,
    webPreferences: {
      nodeIntegration: true,
      webSecurity: false,
      preload: `${__dirname}/preLoad.js`
    }
  })
}

到这里新的弹窗已经有了,那里面的内容要如何填充呢?我们可以参照第一个窗口的做法用win.loadURL()来决定加载html文件。但是react项目打完包只有一个index.html啊,新的窗口应该从哪里加载html呢。接下来我们就来解决这一问题。

首先,在config/webpack.config.js里找到entry。如果没有config文件夹需要先运行命令把我们的config配置文件给暴露出来:

代码语言:javascript
复制
npm run eject

如果你运行了之后报如下错误:

这是因为我们使用脚手架创建一个项目的时候,自动给我们增加了一个.gitignore文件,但是我们本地却没有文件仓库。需要在终端输入如下命令:

代码语言:javascript
复制
git add .
git commit -am "Save before ejecting"

就是用git将项目添加到我们的本地仓库,接下来再执行npm run eject就没有问题了。

然后项目下会多出两个文件夹,config和scripts,我们开发中一般只需关心config文件下的webpack.config.js,paths.js,webpackDevServer.config.js,其他多出来的文件不要管他。下面就是config/webpack.config.js里entry的代码:

这里面就只是显示index的路径,我们需要在config/paths.js里添加我们几个模块的路径:

代码语言:javascript
复制
module.exports = {
  appIndexJs: resolveModule(resolveApp, 'src/index/index'),
  // 添加的模块路径
  appModalJs: resolveModule(resolveApp, 'src/Modal/index'),
}

修改config/webpack.config.js的entry为对象形式:

代码语言:javascript
复制
entry: {
      index: [paths.appIndexJs, isEnvDevelopment && require.resolve('react-dev-utils/webpackHotDevClient')].filter(Boolean),
      modal: [paths.appModalJs, isEnvDevelopment && require.resolve('react-dev-utils/webpackHotDevClient')].filter(Boolean)
    },

添加html配置,同样在config/paths.js里面添加:

代码语言:javascript
复制
appHtml: resolveApp('public/index.html'),
// 新增的html
appModalHtml: resolveApp('public/modal.html'),

config/paths.js里完整的module.exports如下:

代码语言:javascript
复制
module.exports = {
  dotenv: resolveApp('.env'),
  appPath: resolveApp('.'),
  appBuild: resolveApp('build'),
  appPublic: resolveApp('public'),
  appHtml: resolveApp('public/index.html'),
  // 新增的html
  appModalHtml: resolveApp('public/modal.html'),
  appIndexJs: resolveModule(resolveApp, 'src/index'),
  // 添加的模块路径
  appModalJs: resolveModule(resolveApp, 'src/Modal/index'),
  appPackageJson: resolveApp('package.json'),
  appSrc: resolveApp('src'),
  appTsConfig: resolveApp('tsconfig.json'),
  appJsConfig: resolveApp('jsconfig.json'),
  yarnLockFile: resolveApp('yarn.lock'),
  testsSetup: resolveModule(resolveApp, 'src/setupTests'),
  proxySetup: resolveApp('src/setupProxy.js'),
  appNodeModules: resolveApp('node_modules'),
  publicUrlOrPath,
};

在config/webpack.config.js里处理html,在plugins中将原来的HtmlWebpackPlugin进行配置修改,添加一个filename和chunks:

代码语言:javascript
复制
Object.assign(
          {},
          {
            filename: 'index.html',// 添加filename
            chunks: ['index'] //添加chunks
          },

对之前配置的每个页面都复制一个改一下它的template和filename以及chunks:

代码语言:javascript
复制
new HtmlWebpackPlugin(
        Object.assign(
          {},
          {
            inject: true,
            template: paths.appHtml,
            filename: 'index.html',
            chunks: ['index']
          },
          isEnvProduction
            ? {
                minify: {
                  removeComments: true,
                  collapseWhitespace: true,
                  removeRedundantAttributes: true,
                  useShortDoctype: true,
                  removeEmptyAttributes: true,
                  removeStyleLinkTypeAttributes: true,
                  keepClosingSlash: true,
                  minifyJS: true,
                  minifyCSS: true,
                  minifyURLs: true,
                },
              }
            : undefined
        )
      ),
      new HtmlWebpackPlugin(
        Object.assign(
          {},
          {
            inject: true,
            template: paths.appTicketHtml,
            filename: 'ticket.html',
            chunks: ['ticket']
          },
          isEnvProduction
            ? {
              minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeRedundantAttributes: true,
                useShortDoctype: true,
                removeEmptyAttributes: true,
                removeStyleLinkTypeAttributes: true,
                keepClosingSlash: true,
                minifyJS: true,
                minifyCSS: true,
                minifyURLs: true,
              },
            }
            : undefined
        )
      )

然后我们运行npm run build来对react项目进行打包。如果build后报Cannot read property 'filter' of undefined,那么就需要把new ManifestPlugin里的generate属性删掉,这个问题我不是很清楚,从网上也是只搜到了解决方案而没有搜到原因,如果有前端小伙伴明白其中的原因,希望可以指点一二,不胜感激!

至此,我们的react项目已经可以打包出两个html文件和其对应的资源了,我们就用win2.loadURL()使其拥有两个独立的窗口。如下:

代码语言:javascript
复制
 // 创建第二个窗口
  const win2 = new BrowserWindow({
    width: 400,
    height: 300,
    webPreferences: {
      nodeIntegration: true,
      webSecurity: false,
      preload: `${__dirname}/preLoad.js`
    }
  })
  win2.loadURL(url.format({
   pathname: path.join(__dirname, 'dist/index.html'),
   protocol: 'file:',
   slashes: true
 }))

窗口相对独立了我们可以通过electron进程间通讯来控制两个窗口何时打开关闭,达到一个交互效果。当然了,如果要做更多页面也是可以的,我们可以继续优化webpack的配置,做到可以自动打包多个页面,这些我们将来再做介绍。

经过几天的更新,目前算是较为完整的实现了将一个基于react的web应用利用electron变成了一个桌面应用。中间也包含了很多由此引出的问题以及解决思路,当然也存在还没有搞明白的问题,技术略菜,欢迎各位前端小伙伴一起探讨...

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-08-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端Q 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档