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