Currently, I am in the process of developing a Symfony 3 Application with Vite and Vue3 integrated with TypeScript.
To replace Symfony's Webpack Encore, I opted for the Vite Buildtool using this convenient plugin: https://github.com/lhapaipai/vite-bundle
Initially, I followed the migration guide and everything was working smoothly. However, now I seem to be facing an issue where my Vue application is not rendering as expected. Vue Devtools also fail to recognize it. Even when accessing localhost:8000/vue, I am unable to see my components.
The console throws me this error message:
app.js:8 Uncaught ReferenceError: exports is not defined
at app.js:8:23
(anonymous) @ app.js:8
I'm unsure why this is happening all of a sudden. Could there have been something that I missed during the setup? Below are the details of my configuration files.
In case you're wondering, I don't encounter any errors while running `vite dev / npm run dev`.
This is how my `app.vue` looks like:
<script setup lang="ts">
import BaseLayout from "./layout/BaseLayout.vue";
import StickyBanner from "./patterns/StickyBanner.vue";
import ImageSlider from "./components/image-slider.vue";
import BottomMenu from "./components/bottom-menu.vue";
import NavigationBar from "./components/navigation-bar.vue";
import MasonryGallery from "./components/masonry-gallery.vue";
</script>
<template>
<BaseLayout>
<template #header>
<StickyBanner />
<NavigationBar />
<h1>Header</h1>
</template>
<template #main>
<ImageSlider />
<MasonryGallery />
</template>
<template #footer>
<BottomMenu />
<h1>Footer</h1>
</template>
<slot/>
</BaseLayout>
</template>
<style lang="scss" scoped></style>
Here's how my `app.ts` file appears:
/*
* Welcome to your app's main TS file!
*
* We recommend including the built version of this JavaScript file
* (and its CSS file) in your base layout (base.html.twig).
*/
// any CSS you import will output into a single css file (app.css in this case)
import './styles/app.css';
// start the Stimulus application
import './bootstrap';
import 'flowbite';
import {createApp} from "vue";
import App from "./vue/App.vue";
import ModeSwitcher from "./vue/patterns/ModeSwitcher.vue";
import ImageSlider from "./vue/components/image-slider.vue";
import StickyBanner from "./vue/patterns/StickyBanner.vue";
import ServiceInfo from "./vue/components/service-info.vue";
const app = createApp({});
app.component('App', App);
app.component('ModeSwitcher', ModeSwitcher);
app.component('ImageSlider', ImageSlider);
app.component('StickyBanner', StickyBanner);
app.component('ServiceInfo', ServiceInfo);
app.mount('#app');
For my vite configuration settings, they look like this in `vite.config.ts`:
import { defineConfig } from "vite";
import symfonyPlugin from "vite-plugin-symfony";
import vue from "@vitejs/plugin-vue";
/* if you're using React */
// import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [
/* react(), // if you're using React */
symfonyPlugin(),
vue(), // write this
],
resolve: {
alias: {
vue: 'vue/dist/vue.esm-bundler.js',
}
},
base: '/build/',
build: {
outDir: './public/build',
rollupOptions: {
input: {
app: "./assets/app.ts",
/* you can also provide css files to prevent FOUC */
styles: "./assets/styles/app.css"
},
}
},
});
This is how my `tsconfig.json` file is configured:
{
"compilerOptions": {
"module": "commonjs",
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true
},
}
And finally, here are the contents of my `index.html.twig` file:
{% extends 'base.html.twig' %}
{% block title %}Hello VueController!{% endblock %}
{% block body %}
Test
<div>
<div id="app">
<app></app>
</div>
</div>
{% endblock %}
As for my `base.html.twig` template, it looks like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Welcome!{% endblock %}</title>
<link rel="icon"
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text></svg>">
{# Run `composer require symfony/webpack-encore-bundle` to start using Symfony UX #}
{% block stylesheets %}
{{ vite_entry_link_tags('app') }}
{% endblock %}
{% block javascripts %}
{{ vite_entry_script_tags('app') }}
{% endblock %}
<script>
// On page load or when changing themes, best to add inline in `head` to avoid FOUC
if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark');
console.log('dark')
} else {
document.documentElement.classList.remove('dark')
console.log('light')
}
</script>
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
Last but not least, here's what my `package.json` contains:
{
"devDependencies": {
"autoprefixer": "^10.4.14",
"core-js": "^3.23.0",
"postcss": "^8.4.21",
"postcss-loader": "^7.1.0",
"regenerator-runtime": "^0.13.9",
"tailwindcss": "^3.3.1",
"ts-loader": "^9.4.2",
"unplugin-vue-components": "^0.24.1",
"vue": "^3.0",
"vue-loader": "^17.0.1"
},
"license": "UNLICENSED",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build"
},
"dependencies": {
"@headlessui/vue": "^1.7.12",
"@vitejs/plugin-vue": "^4.1.0",
"flowbite": "^1.6.5",
"sass": "^1.62.0",
"vite": "^4.2.1",
"vite-plugin-symfony": "^0.7.6"
},
"type": "module"
}