Home > other >  Vue3 doesn't seem to be loaded in Rails 7 shakapacker app
Vue3 doesn't seem to be loaded in Rails 7 shakapacker app

Time:06-21

I created a new project for a shopify app with rails 7 and shakapacker. I want to use Vue components in my .slim files. The problem is that Vue doesn't seem to be loaded in my app, although I don't get any errors.

Here is what I did:

// config/webpack/rules/vue.js

const { VueLoaderPlugin } = require('vue-loader')

module.exports = {
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin()
  ],
  resolve: {
    extensions: [
      '.vue'
    ]
  }
}
// config/webpack/webpack.config.js

const { webpackConfig, merge } = require('shakapacker')
const vueConfig = require('./rules/vue')

module.exports = merge(vueConfig, webpackConfig)
// app/javascript/packs/application.js

import HelloWorld from '../components/HelloWorld'

import { createApp } from 'vue'
const app = createApp({
  el: '#app'
})

app.component('helloworld', HelloWorld)

document.addEventListener('DOMContentLoaded', () => {
  app
})
// app/javascript/components/HelloWorld.vue

<template>
  <h1>Hello world</h1>
</template>

<script>
export default {
  name: 'HelloWorld'
}
</script>
/ app/views/layouts/embedded_app.slim

doctype html
html[lang="en"]
  head
    meta[charset="utf-8"]
    - application_name = ShopifyApp.configuration.application_name
    title
      = application_name
    = stylesheet_link_tag "application", "data-turbo-track": "reload"
    = javascript_pack_tag 'application', 'data-turbolinks-track': 'reload'
    = csrf_meta_tags

  body
    #app
      .wrapper
        main[role="main"]
          = yield

    = content_tag(:div, nil, id: 'shopify-app-init', data: { api_key: ShopifyApp.configuration.api_key,
        shop_origin: @shop_origin || (@current_shopify_session.shop if @current_shopify_session),
        host: @host,
        debug: Rails.env.development? })

And finally, the view where I just want to display the HelloWorld.vue component:

/ app/views/home/index.slim

helloworld

However, nothing is displayed and I have no errors. I tried to modify the creation of the app in this way, to see if the log appears:

// app/javascript/packs/application.js

import HelloWorld from '../components/HelloWorld'

import { createApp } from 'vue'
const app = createApp({
  el: '#app',
  created () {
    console.log('ok')
  }
})

app.component('helloworld', HelloWorld)

document.addEventListener('DOMContentLoaded', () => {
  app
})

but then again, I have nothing in console, so I'm not even sure that the app is well rendered. On the other hand, I checked that the DOMContentLoaded event is indeed triggered and it is.

I'm not very comfortable with webpack so I don't know if something is wrong with my configuration, I followed shakapacker's README.

I don't think this is related, but the app is rendered in a Shopify test store via an Ngrok tunnel.

I don't know where to look anymore... Does anyone have an idea? Thanks in advance

CodePudding user response:

I haven't written any VueJS in a long time, but this is usually what I do in my application.js using React & Shopify Polaris components.

function initialize() {
  const rootElement = document.getElementById('app')
  const root = createRoot(rootElement);

  /* some app bridge code I removed here */

  /* react 18 */
  root.render(
    <BrowserRouter>
      /* ... */
    </BrowserRouter>
  )
}

document.readyState !== 'loading' ?  initialize() : document.addEventListener('DOMContentLoaded', () => initialize())

If your <div id="app"> is EMPTY when inspected with browser tools, my first guess would be you're creating an instance, but not actually rendering it in the end.

An application instance won't render anything until its .mount() method is called.

https://vuejs.org/guide/essentials/application.html#mounting-the-app

I would've commented to ask first, but I don't have enough reputation points to do so

  • Related