Currently, I am dealing with a situation in a legacy Rails application that has undergone some migration to integrate Webpacker and Vue. Additionally, we are utilizing a legacy script loaded through a CDN that also requires Vue. However, instead of bundling Vue into the script, we are aiming to utilize the existing Vue instance within the Rails app.
After referencing this question on Stack Overflow How to expose Vue as global object, I have managed to expose the Vue object at Vue.default
using expose-loader. Essentially, the exposed "Vue" object is a Module where the actual Vue object is nested within Vue.default
.
My progress has been guided by extensive research on relevant documentation and articles. The following were the most helpful resources:
While my current approach works, I am skeptical about its efficiency. I am now exploring a potentially "more correct" method of exposing Vue directly, without nesting it within the Module default.
My Experiment
To test a new approach, I created a new Rails 6 application from scratch. After adding the necessary JS dependencies using the following commands:
yarn install
yarn add vue
yarn add -D expose-loader
yarn add -D webpack-dev-serer
rails webpacker:install
I went ahead to configure the expose-loader in config/webpack/development.js
environment.loaders.append('expose', {
test: require.resolve('vue'),
use: [{
loader: 'expose-loader',
options: 'Vue'
}]
})
Subsequently, I created a basic page and set it as the root route. Then, I created an entry JavaScript file at
app/javascript/packs/application.js
import Vue from 'expose-loader?Vue!vue'
console.log({ pack: Vue })
Within the application layout, under
javascript_pack_tag 'application'
, I included:
<script>
try {
console.log({ layout: Vue })
} catch (error) {
console.warn('Global Vue not found')
}
</script>
Upon inspecting the browser console, I observed
{ pack: ƒ Vue(options) }
{ layout: Module
default: ƒ Vue(options) }
I further experimented with various configurations for the expose-loader in config/webpack/development.js
, but the results varied.
test: require.resolve('vue/dist/vue.esm.js')
// or
test: require.resolve('vue/dist/vue.esm.js').default
// or
test: require.resolve('expose-loader?Vue!vue')
// and different permutations of that.
Additionally, I attempted a different approach by directly assigning Vue to the window object from my application.js pack file. Although it functions, it doesn't seem like the optimal solution. Is there a more appropriate method?
The Question
What is the recommended way to expose the Vue object managed by Webpacker so that any non-Webpacker managed script can access it? In other words, how can it be made available on the window
object?