为生产构建我的电子 vue 应用程序后出现白屏

Posted

技术标签:

【中文标题】为生产构建我的电子 vue 应用程序后出现白屏【英文标题】:White screen after building my electron-vue app for production 【发布时间】:2020-02-13 06:20:18 【问题描述】:

我正在构建一个具有多个窗口的电子 vue 应用程序,我正在使用 vue-router。

该应用在从 Visual Studio Code 终端(开发模式)运行时运行良好,但在为生产构建它之后,我得到一个白屏。

这是我的代码

public/index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <link rel="icon" href="<%= BASE_URL %>favicon.ico">
  <title>EmaFlow Work Sessiong Tracker</title>
</head>

<body>
  <noscript>
    <strong>We're sorry but statement-ts doesn't work properly without javascript enabled. Please enable it to
      continue.</strong>
  </noscript>

  <div id="app" class="h-100"></div>

  <!-- built files will be auto injected -->
</body>

</html>

src/App.vue

<template>
  <div id="app" class="h-100">
    <router-view />
  </div>
</template>

src/router.ts

import Vue from 'vue';
import Router from 'vue-router';

import LoginWindow from '@/views/LoginWindow.vue';
import MainWindow from '@/views/MainWindow.vue';

Vue.use(Router);

export default new Router(
  routes: [
    
      path: '/',
      name: 'login',
      component: LoginWindow,
    ,
    
      path: '/main',
      name: 'main',
      component: MainWindow,
    ,
  ],
);

src/main.ts

import Vue from 'vue';
import VeeValidate from 'vee-validate';
import VueTimers from 'vue-timers'

import App from './App.vue';
import router from './router';

Vue.use(VeeValidate);

Vue.use(VueTimers)

Vue.config.productionTip = false;

new Vue(
  router,
  render: (h) => h(App),
).$mount('#app');

import $ from 'jquery'
import 'bootstrap/dist/css/bootstrap.min.css'
import 'bootstrap/dist/js/bootstrap.bundle.min.js'
import '@fortawesome/fontawesome-free/js/all.min.js';

src/background.ts

'use strict'

import  app, protocol, BrowserWindow, ipcMain, Event  from 'electron'
import 
  createProtocol,
  installVueDevtools
 from 'vue-cli-plugin-electron-builder/lib'

const isDevelopment = process.env.NODE_ENV !== 'production'

// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([ scheme: 'app', privileges:  secure: true, standard: true  ])

const appWindows: BrowserWindow[] = [];

function createWindow(slug: string, options?: object) 
  const defaultOptions = 
    width: 800,
    height: 600,
    frame: false,
    webPreferences: 
      nodeIntegration: true,
    ,
  ;
  const windowOptions = Object.assign(, defaultOptions, options);
  const window = new BrowserWindow(windowOptions);
  appWindows.push(window);

  if (process.env.WEBPACK_DEV_SERVER_URL) 
    // Load the url of the dev server if in development mode
    window.loadURL(process.env.WEBPACK_DEV_SERVER_URL as string + '/#' + slug);
    window.webContents.openDevTools();
   else 
    createProtocol('app')
    // Load the index.html when not in development
    window.loadURL('app://./index.html' + '/#' + slug);
  

  window.on('closed', () => 
    appWindows.splice(appWindows.indexOf(window), 1);
  );


function createLoginWindow() 
  createWindow('/', 
    width: 400,
    height: 300,
    resizable: isDevelopment,
  );


// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => 
  if (isDevelopment && !process.env.IS_TEST) 
    // Install Vue Devtools
    try 
      await installVueDevtools();
     catch (e) 
      // console.error('Vue Devtools failed to install:', e.toString());
    
  

  createLoginWindow();
);

app.on('activate', () => 
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (appWindows.length === 0) 
    createLoginWindow();
  
)

// Quit when all windows are closed.
app.on('window-all-closed', () => 
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') 
    app.quit()
  
)

ipcMain.on('open-window', (e: Event, arg: WindowParams) => 
  createWindow(arg.route, arg.options);
);

// Exit cleanly on request from parent process in development mode.
if (isDevelopment) 
  if (process.platform === 'win32') 
    process.on('message', data => 
      if (data === 'graceful-exit') 
        app.quit()
      
    )
   else 
    process.on('SIGTERM', () => 
      app.quit()
    )
  

package.json


  "name": "emaflow-worksession-tracker",
  "version": "0.1.0",
  "private": true,
  "scripts": 
    "lint": "vue-cli-service lint",
    "build": "vue-cli-service electron:build",
    "serve": "vue-cli-service electron:serve",
    "postinstall": "electron-builder install-app-deps",
    "postuninstall": "electron-builder install-app-deps"
  ,
  "main": "background.js",
  "dependencies": 
    "axios": "^0.19.0",
    "bootstrap": "^4.3.1",
    "core-js": "^2.6.10",
    "howler": "^2.1.2",
    "jquery": "^3.4.1",
    "popper.js": "^1.15.0",
    "typescript": "^3.6.4",
    "vee-validate": "^2.2.15",
    "vue": "^2.6.10",
    "vue-class-component": "^7.0.2",
    "vue-property-decorator": "^8.2.2",
    "vue-router": "^3.1.3",
    "vue-timers": "^2.0.4"
  ,
  "devDependencies": 
    "@fortawesome/fontawesome-free": "^5.11.2",
    "@vue/cli-plugin-babel": "^3.12.0",
    "@vue/cli-plugin-typescript": "^3.12.0",
    "@vue/cli-service": "^3.12.0",
    "electron": "^5.0.11",
    "stylus": "^0.54.7",
    "stylus-loader": "^3.0.2",
    "vue-cli-plugin-electron-builder": "^1.4.0",
    "vue-template-compiler": "^2.6.10"
  

在应用启动时,将显示一个登录窗口,成功登录后,登录窗口将关闭并打开另一个窗口。

为了打开一个窗口,我在background.ts 中创建了函数createWindow,它将路由器路径作为第一个参数。例如,要创建登录窗口,我调用createWindow('/', options),并在成功登录后创建主应用程序窗口,我编写createWindow('/main', options)

我认为我的问题出在window.loadUrl 中的createWindow 中的background.ts 中,但我不确定生产模式的正确网址应该是什么。

请提前告知和感谢。

【问题讨论】:

当一个 js 错误将阻止进一步的 js 评估时,我已经看到了这种问题。您可以尝试从 index.html 中删除脚本标记,以查看是否创建了登录页面。对此类问题也有帮助的是在您的 prod 版本中打开 DevTools 并在控制台中查看错误。 @anwar 为什么你有自定义协议('app')?检查 loadURL 函数是否支持自定义协议? 我从 index.html 中删除了 script 标签,并在 main.ts 中导入了 jquery。我在 prod 版本中打开了开发工具,控制台中没有错误但仍然出现白屏,它没有加载 index.html,我在开发工具中看不到 index.html 的内容,我只看到空的正文。关于应用程序协议,老实说我不知道​​它是什么,我从一些样板或教程中复制了这些代码行。如果我删除这些代码行,我会在控制台中收到类似“无法加载资源:net::ERR_UNKNOWN_URL_SCHEME app://./js/app.7cbb0157.js:1”的错误,看起来需要此协议。 【参考方案1】:

最后我可以让window.loadUrl 为生产版本工作,如下所示:

createProtocol('app');
window.loadURL(formatUrl(
   pathname: path.join(__dirname, 'index.html'),
   protocol: 'file',
   slashes: true
));

上面的代码可以运行,但是它只打开了登录窗口,它在 vue-router 路由列表中有路径“/”。

要为“/main”之类的另一条路由打开一个窗口,我尝试将哈希和路由附加到路径名,如下所示:

window.loadURL(formatUrl(
  pathname: path.join(__dirname, 'index.html#', slug),
  protocol: 'file',
  slashes: true
));

但它不起作用,在开发工具网络选项卡上我看到了这个错误:

名称:index.html%23/ 状态:(已屏蔽:其他)

请指教

编辑:在将hash 属性添加到传递给formatUrl 的选项对象后,所有工作都可以正常工作,而不是手动附加到pathname

window.loadURL(formatUrl(
   pathname: path.join(__dirname, 'index.html'),
   protocol: 'file',
   slashes: true,
   hash: slug
));

【讨论】:

只需使用不带formatUrlpath.join 方法,因为formatUrl 对您给定的url 进行编码,但您需要将# 作为# 而不是html 编码形式。

以上是关于为生产构建我的电子 vue 应用程序后出现白屏的主要内容,如果未能解决你的问题,请参考以下文章

为啥我在构建 Flutter Web 时会出现白屏

Vue js 开发代码运行良好,但生产版本在打开时出现空白白屏

Angular Electron,重新加载页面后出现白屏

运行我的颤振 Web 应用程序后出现白屏

启动画面后出现白屏 - Worklight 应用程序

使用电子生成器构建后,电子应用程序未加载 index.html,甚至没有给出错误