Skip to content

Using VueJS with Webpack

Julian Knight edited this page Jan 26, 2019 · 11 revisions

WORK IN PROGRESS The basics are correct but it would be better to use the VueJS simple example as the basis so that people can compare this to the non-build way of working.

Users of frameworks that normally use a build step to deploy code - such as WebPack - sometimes seem to struggle with using uibuilder. This page aims to explain a simple approach that works.

Before starting however, I should say that you don't need any of this unless you are creating a complex VueJS single page app. Check out the simple Vue example, that doesn't use a build step and it works fine, VueJS is far more efficient than Angular and a build step is much less critical. I've also built a more complex Vue-based home dashboard that receives large amounts of information every 30-60 seconds and it works well even on mobile devices - still no build step involved.

Also note that you should be able to adapt these instructions to other frameworks that also want a build stage. Please feel free to contribute other pages with instructions specific to other frameworks.

Setup

  1. Install the uibuilder node and the front-end framework you need. Here we will use VueJS as an example.
  2. Add an instance of the uibuilder node to your Node-RED flow along with any data you want to feed to it and any output processing. See the basic VueJS page of this WIKI for an example. Deploy the flow.
  3. You now have a folder containing the example source for your UI page. It is probably something like this:
~/.node-red/uibuilder
    uibuilder
        <instance-url>
            dist
            src
                index.css
                index.html
                index.js
                manifest.json

Where <instance-url> matches the url you specified in the uibuilder node instance.

Install dependencies

On a command line, navigate to the <instance-url> folder then do the following@

npm init -y
npm --save install vue
npm install --save-dev webpack webpack-cli vue-loader vue-template-compiler vue-style-loader css-loader

If you want to, you can make vue a dev-dependency too since the version that is used by uibuilder is installed in your ~/.node-red userDir folder.

You may also wish to add other vue components such as vue-router and bootstrap-vue as desired.

Create a build script

Add the following to the package.json file that has been created for you in the <instance-url> folder:

  "scripts": {
    "build": "webpack --config ./webpack.config.dev.js"
  },

Create the webpack config file webpack.config.dev.js:

'use strict'
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
  mode: 'development',
  entry: [
    './src/index.js'
  ],
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: 'vue-loader'
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin()
  ]
}

Add your root VueJS App

In the src sub-folder, make sure you have the standard 3 index.(css|html|js) files and add another called App.vue

<template>
    <div>
        <h1>Hello World!</h1>
    </div>
</template>

Obviously, this is just a dummy. You will want to replace it with something meaningful.

This file will be included using your index.js file and webpack will translate it into JavaScript via the vue-loader plugin.

Change the index.html file

Alter the index.html file like this:

<body>
    <h1>OK Vue</h1>
    <div id="app"></div>

    <script src="/uibuilder/socket.io/socket.io.js"></script>
    <!-- Note no leading / -->
    <script src="./main.js" type="text/javascript"></script>

</body>

Keep the rest of the file the same.

Note that you are not including any of the "standard" JavaScript files now except for socket.io, they have all been packed into a single file. You can also include the Socket.IO client in your build if you like but there are some complexities, please look them up and deal with them rather than raising an issue with uibuilder.

This again is an absolutely bare minimum example of course.

Change the index.js file

// NOTE: If no path is given, webpack will look for installed modules
//       If a path is given, it is relative to the folder containing this file
import Vue from 'vue'
import App from './App.vue'
// NOTE: Adjust the relative path (or use an absolute path) according to the acutal
//       location of the uibuilderfe.js file
//       In most installations, this will be 3 levels above the folder containing this file
import uibuilder from './../../../../node_modules/node-red-contrib-uibuilder/nodes/src/uibuilderfe.js'

new Vue({
    el: '#app',
    render: h => h(App),
    mounted: function(){
        console.debug('Vue:mounted - setting up uibuilder watchers')

        console.log(uibuilder)

        // Save confusion by keeping a specific reference to this Vue app
        const vueApp = this

        // If msg changes - msg is updated when a standard msg is received from Node-RED over Socket.IO
        // Note that you can also listen for 'msgsReceived' as they are updated at the same time
        // but newVal relates to the attribute being listened to.
        uibuilder.onChange('msg', function(newVal){
            console.debug('Vue:mounted:UIBUILDER: property msg changed! ', newVal)

        }) // ---- End of uibuilder.onChange() watcher function ---- //

    }, // --- End of mounted hook --- //
})

I will be trying to simplify the include for uibuilderfe.js in a future release.

Once again, this is a bare minimum example.

Getting it all to work

Now that you have everything available in the src and root folders, you can (from the root folder) run npm run build which will pack everything together and create dist/main.js.

Finally, you need to copy your manifest.json, index.html and index.css files from src to dest and then either redeploy your uibuilder node or restart Node-RED.

That last step makes the uibuilder instance switch from using the src folder to using the dist folder (something that I will improve in a future release of uibuilder). You only have to do that once.

Of course, you now need to remember to run the build step whenever you change a JavaScript or .vue file.

Troubleshooting

If you have any issues, firstly pare everything back to this minimal example so that you know you have the basics correct.

Then add complexity piece-by-piece until you find the issue. This example works so make sure you've followed the steps carefully.

Final folder/file layout

You should end up with something like this:

~/.node-red/uibuilder/
    uibuilder/
        <instance-url>/
            webpack.config.dev.js
            package.json
            node_modules/
            dist/
                index.css
                index.html
                main.js
                manifest.json
            src/
                index.css
                index.html
                index.js
                manifest.json

Optimising

TBC

It isn't necessarily the best approach to have a single, very large js file with everything packed into it.

Final note

If the front-end libraries that you are using don't have any CSS or other assets that need to be loaded in your html page - such as images for example. Then you don't actually need to install the library into ~/node-red as the standard instructions say.

There is no real harm in installing them - other than using up some disk space and resources - but any code won't be used since you are using webpack to pack all of the code into your dist/main.js file.

Improving this page

I am far from being a webpack expert so I am certain there are better ways to do things. If you find a better way, please get in touch so that everyone can benefit.

Thanks, Julian.

Clone this wiki locally