ElMassimo / vite-plugin-full-reload

♻️ Automatically reload the page when files are modified
MIT License
147 stars 8 forks source link

feat: Add plugin option "type" #1

Closed rehhouari closed 3 years ago

rehhouari commented 3 years ago

This allows specifying the type instead of hard-coded full-reload. This is useful in custom hot-reloading implementations (with a WebSocket listener).

ElMassimo commented 3 years ago

Hi Rafik, nice to see you here!

Given the scope of this plugin is very small, and full-reload being its main premise, I'm tempted to keep the amount of options low.

Would you describe how you are using it for custom HMR?

rehhouari commented 3 years ago

Given the scope of this plugin is very small, and full-reload being its main premise, I'm tempted to keep the amount of options low.

Understandable! I'll just implement it on my own plugin

Would you describe how you are using it for custom HMR?

So I'm not using Vue, but Alpine.js. Since it don't have a router I made a simple one.

It can be accessed from Javascript so instead of a full-reload It's smoother to reload the view only.

Behind the scenes, when the files are edited, the views are compiled with the Vite plugin I made. And in the client side it just fetch that is copied to public by the Vite plugin.

Here's the WebSocket listener that I made by looking at Vite's source code:

const socketProtocol = location.protocol === 'https:' ? 'wss' : 'ws';
const socketHost = \`\${location.hostname}:3000\`;
const socket = new WebSocket(\`\${socketProtocol}://\${socketHost}\`, 'vite-hmr');

// Listen for messages
socket.addEventListener('message', async ({ data }) => {
    handleMessage(JSON.parse(data));
    console.log(data)
});

async function handleMessage(payload) {
    if (payload.type == 'custom') {
        reload(payload)
    }
}

function reload(payload) {
    if (
        payload.path.includes('/src/pages') ||
        payload.path.includes('/src/layouts')
    ) {
        console.log('Rapide: reloading view!')
        window.PineconeRouter.navigate(window.PineconeRouter.currentContext.path);
    }
}
ElMassimo commented 3 years ago

Gotcha! If you are referring to this plugin, I think an alternative to creating your own websockets connection would be to reuse Vite's connection and instead inject HMR information in the "views" instead.

This example might be useful—in your case you could use import.meta.hot.accept to reload using window.PineconeRouter.navigate whenever a relevant file is modified.

rehhouari commented 3 years ago

Yes that's it, thanks a lot for taking the time to review it!

I Didn't know reusing the Vite connection was possible, I'll try it out, that's very helpful ^^

ElMassimo commented 3 years ago

You can also emit custom events that will be handled by the Vite client 😃

@rehhouari For example:

handleHotUpdate({ file, server }) {
  const paths = ['/src/pages', '/src/layouts']
  if (paths.some(path => file.includes(path)) {
    server.ws.send({ type: 'custom', event: 'pinecone:reload', data: {} })
    return []
  }
}

Client code should register corresponding handler using the HMR API (this could be injected by the same plugin's transform hook):

if (import.meta.hot) {
  import.meta.hot.on('pinecone:reload', (data) => {
    console.log('Rapide: reloading view!')                               
    window.PineconeRouter.navigate(window.PineconeRouter.currentContext.path)
  })
}
rehhouari commented 3 years ago

You can also emit custom events that will be handled by the Vite client

@rehhouari For example:

handleHotUpdate({ file, server }) {
  const paths = ['/src/pages', '/src/layouts']
  if (paths.some(path => file.includes(path)) {
    server.ws.send({ type: 'custom', event: 'pinecone:reload', data: {} })
    return []
  }
}

Client code should register corresponding handler using the HMR API (this could be injected by the same plugin's transform hook):

if (import.meta.hot) {
  import.meta.hot.on('pinecone:reload', (data) => {
    console.log('Rapide: reloading view!')                                 
    window.PineconeRouter.navigate(window.PineconeRouter.currentContext.path)
  })
}

awesome!! working on it