Med: HMR in Meteor + VueJS

@gusto and others, I read on a post of yours that you have HMR working with Meteor + VueJS.

Will you please help us understand how to get this working with our own projects? Maybe point us to an article or video, or even a repo example would be nice.

I have a very small project I’m testing Meteor + VueJS on with right now, so this is the perfect time to learn these techniques and test the limits. :slight_smile:

There’s no real point to point to an article or a video, because with Akryum’s packages, it just works, out of the box. That, of course, is restricted to the dev environment.

If you make a change in your client code, f.e. change a value of data property or add some new HTML element, by default you should trigger the hot module reload, making the change instantly visible in the browser, without the browser doing traditional Meteor refresh.

You didn’t notice such behaviour? Does it not work for you?

Basically, a Hot Module Replacement system swap in place some modules if they are compatible. akryum:vue-component enable this for all your .vue modules. It does that by starting a socket server in your meteor server, and has some code run on the meteor client that connects to it with web sockets. The compiler will then send new component definitions when they change to the client, that will swap them on the Vue instances while preserving any state that they might have. That way, your Vue components will instantly update (including templates, scripting, methods and style) when you save them! :slight_smile:

The limit of this system is that it can only apply to compatible modules. For example, if you change a simple .js file, which the system in akryum:vue-component doesn’t support, it will trigger a normal Meteor client refresh.
One caveat: if you save both .vue files and other files at the same time, the HMR system may not detect that a full page refresh is needed, so you have to manually hit F5! :stuck_out_tongue:

Maybe we could see this system evolve and become more integrated into Meteor so that it can hot replace other types of modules like React components (which has another similar package for HMR) and plain JavaScript files.

6 Likes

That’s awesome, it would really great if we have for other views as well, specially React.

Bat signaling @zodern he might be interested in this.

1 Like

Ideally we would lean as much as possible on each framework’s own HMR system and just provide the necessary connectors to hook into Meteor’s system

1 Like

After struggling with VueJS & HMR for a little, I finally figured out a fully working setup.

When using the standard way of developing a project with Meteor and running the built-in server on localhost:3000 HMR for VueJS works out of the box.

I am using Phusion Passenger with nginx, even for my development environment, because it provides me with the additional benefit of serving static files and resources through nginx and also enables SSL (via letsencrypt)

The key is to set the proper environment variables. Here is my nginx server definition with meteor running on port 6000 (there probably is room for improvement considering my nginx config, but this is how I got it working)

server {
    server_name project.example.com;
    # Turn off Passenger
    passenger_enabled off;
    # any location for static assets
    location /assets {
        #gzip_static on;
        root /Users/jamgold/Meteor/project.assets;
    }
    # important for HMR
    location /socket.io {
        add_header Access-Control-Allow-Origin *;
        proxy_pass http://127.0.0.1:6003;
        proxy_http_version 1.1;
        proxy_read_timeout 36000s;
        proxy_send_timeout 36000s;
        proxy_set_header Upgrade $http_upgrade; # allow websockets
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header X-Forwarded-For $remote_addr; # preserve client IP
        proxy_set_header Host $host;
        #
        # this setting allows the browser to cache the application in a way compatible with Meteor
        # on every application update the name of CSS and JS file is different, so they can be cache infinitely (here: 30 days)
        # the root path (/) MUST NOT be cached
        if ($uri != '/') {
            expires 30d;
        }
    }
    # the actual meteor project server running on port 6000
    location / {
        proxy_pass http://127.0.0.1:6000;
        proxy_http_version 1.1;
        proxy_read_timeout 36000s;
        proxy_send_timeout 36000s;
        proxy_set_header Upgrade $http_upgrade; # allow websockets
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header X-Forwarded-For $remote_addr; # preserve client IP
        proxy_set_header Host $host;
        #
        # this setting allows the browser to cache the application in a way compatible with Meteor
        # on every application update the name of CSS and JS file is different, so they can be cache infinitely (here: 30 days)
        # the root path (/) MUST NOT be cached
        if ($uri != '/') {
            expires 30d;
        }
    }
    # listen 80;
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/project.example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/project.example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

The important part is to start Meteor with the following environment variables

export ROOT_URL="https://project.example.com"
export HMR_URL="https://project.example.com"
# instead of creating a .cache folder in the meteor project directory
export BABEL_CACHE_DIR="/tmp/project.cache"
meteor --port 6000

Developing VueJS with Meteor and HMR is an absolute bliss :slight_smile:

5 Likes