1. Create VueJS project

Install the Vue CLI if you don’t have it.

npm install -g @vue/cli

Create a Vue project inside the project directory.

vue create vue

Here, I chose VueJS 2 and named it “vue”.

Start the dev server.

cd vue
npm run serve

2. Create basic PyQt app

import os
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtWebChannel import *


class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

This will just show a blank window.

3. Load the VueJS app with QWebEngineView

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        view = self.view = QWebEngineView()
        self.view.setUrl(QUrl('http://localhost:8080'))
        self.setCentralWidget(self.view)

This assumes that the VueJS dev server is running locally on port 8080.

4. Show dev tools in separate dialog for debugging

dev_view = QWebEngineView()
self.view.page().setDevToolsPage(dev_view.page())
d = QDialog(self)
l = QVBoxLayout()
d.setLayout(l)
l.addWidget(dev_view)
d.show()

Alternatively, you can run the program with --enable-logging, then the messages from the VueJS app will show up in the console where you started the Python program from.

5. Build the VueJS app for distribution

Add a file named vue.config.js with the following content into the vue directory.

module.exports = {
  publicPath: './'
}

This ensures that the paths in the build output are relative.

Then build the app.

npm run build

Change the Python app to use the built version.

self.view.setUrl(QUrl.fromLocalFile(
    os.path.join(os.path.dirname(os.path.realpath(__file__)),
                 'vue/dist/index.html')))

Done.