Vue router not routing with URL paths - vue.js

So I'm working with Vue 3 and Vue Router 4 and I'm having an issue when running my code with webpack-dev-server. Whenever I run my app webpack-dev-server --mode development the landing page looks great and loads everything from my App.vue file. However, whenever I change the route from the base route / to my new component /test it just loads the same exact view as the base route. I've been browsing for hours and can't seem to figure out what's wrong when I'm sure it's a simple fix. Here's the current structure of my directory:
src
components
Homepage.vue
router
index.js
App.vue
index.html
main.js
package.json
webpack.config.js
here is what's inside some of those important files
src/router/index.js
import Vue from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import App from '../App.vue'
import Homepage from '../components/Homepage.vue'
const routes = [
{ path: '/', component: App },
{ path: '/test', component: Homepage }
]
const router = createRouter({
history: createWebHistory(),
routes: routes
})
export default router
src/main.js
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
createApp(App)
.use(router)
.mount('#app');
package.json
{
"name": "web",
"version": "1.0.0",
"description": "",
"scripts": {
"start": "node index.js",
"serve": "webpack-dev-server --mode development",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
},
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^1.2.5",
"bootstrap": "^5.2.1",
"express": "^4.18.1",
"uuid": "^9.0.0",
"vue": "^3.2.39",
"vue-router": "^4.0.13"
},
"devDependencies": {
"#babel/core": "^7.19.0",
"#babel/preset-env": "^7.19.0",
"babel-loader": "^8.2.5",
"css-loader": "^6.7.1",
"html-webpack-plugin": "^5.5.0",
"vue-loader": "^17.0.0",
"vue-style-loader": "^4.1.3",
"vue-template-compiler": "^2.7.10",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.11.0",
"webpack-merge": "^5.8.0"
}
}
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
// const VueLoaderPlugin = require('vue-loader/lib/plugin');
const { VueLoaderPlugin } = require('vue-loader');
module.exports = {
entry: './src/main.js',
output: {
publicPath: "/"
},
devServer: {
static: {
directory: path.join(__dirname, 'public'),
},
allowedHosts: 'all',
compress: true,
https: true,
historyApiFallback: true
},
module: {
rules: [
{ test: /\.js$/, use: 'babel-loader' },
{ test: /\.vue$/, use: 'vue-loader' },
{ test: /\.css$/, use: ['vue-style-loader', 'css-loader']},
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
new VueLoaderPlugin(),
]
};
I tried modifying my routes, installing new packages/libraries, messing with my webpack config file, copying over loads of code from online, but alas, nothing worked.

Related

can not resolve Uncaught TypeError: vue__WEBPACK_IMPORTED_MODULE_0__.default is undefined

I am working on vue js 2 version and I needed to download font-awsome library for styling purpose. However, when I downloaded the files it seemed not compatible with my project so I deleted/uninstalled them (the font-awsome libraries), and then all of a sudden when I tried to refresh the server I got this error in the console :
Uncaught TypeError: vue__WEBPACK_IMPORTED_MODULE_0__.default is
undefined
Note that the code was working fine before installing and uninstalling the the font-awsome libraries, I don't really know what happened I also did try to ctrl + z to restore the main.js but is still showing the same error.
1- main.js:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import VueFirestore from 'vue-firestore'
import JQuery from 'jquery'
import {BootstrapVue, IconsPlugin} from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.min.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import 'bootstrap/dist/js/bootstrap.min.js'
import './assets/app.scss'
import swal from 'sweetalert2';
// import VoerroTagsInput from '#voerro/vue-tagsinput';
Vue.use(BootstrapVue)
Vue.use(IconsPlugin)
window.$ = JQuery
Vue.use(VueFirestore, {
key: 'id', // the name of the property. Default is '.key'.
enumerable: true // whether it is enumerable or not. Default is true.
})
Vue.use(VueFirestore)
Vue.config.productionTip = false
// Make BootstrapVue available throughout your project
// Vue.use(createPopper)
let app = '';
if(!app){
new Vue({
router,
render: h => h(App)
}).$mount("#app");
}
window.Swal = swal;
const Toast = Swal.mixin({
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 3000
});
window.Toast = Toast;
2- index.js:
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'books',
component: () => import('../components/books')
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
3- package.json:
{
"name": "vue-firebase-crud",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"bootstrap": "^4.5.3",
"bootstrap-vue": "^2.22.0",
"core-js": "^3.8.3",
"firebase": "^8.10.0",
"jquery": "^3.6.1",
"sweetalert2": "^11.4.37",
"vue-firestore": "^0.3.30",
"vue-router": "^3.6.5",
"vue2-editor": "^2.10.3"
},
"devDependencies": {
"#babel/core": "^7.12.16",
"#babel/eslint-parser": "^7.12.16",
"#vue/cli-plugin-babel": "~5.0.0",
"#vue/cli-plugin-eslint": "~5.0.0",
"#vue/cli-service": "~5.0.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"node-sass": "^7.0.3",
"sass": "^1.55.0",
"sass-loader": "^13.1.0",
"vue-template-compiler": "^2.6.14"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "#babel/eslint-parser"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
4- error in console:

Vue 3 - Dynamic require of "highcharts" is not supported

I am trying to include highcharts-vue like this:
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import HighchartsVue from "highcharts-vue";
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.use(HighchartsVue);
app.mount('#app')
But I'm getting the error:
Dynamic require of "highcharts" is not supported
package.json
{
"name": "mwc-web",
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview --port 5050"
},
"dependencies": {
"#popperjs/core": "^2.11.4",
"bootstrap": "^5.1.3",
"bootstrap-vue-3": "^0.1.9",
"highcharts": "^10.0.0",
"highcharts-vue": "^1.4.0",
"moment": "^2.29.1",
"pinia": "^2.0.11",
"vue": "^3.2.31",
"vue-router": "^4.0.12"
},
"devDependencies": {
"#vitejs/plugin-vue": "^2.2.2",
"#vue/cli-plugin-babel": "^5.0.4",
"sass": "^1.49.9",
"sass-loader": "^12.6.0",
"vite": "^2.8.4"
}
}
vite.config.js
import { fileURLToPath, URL } from 'url'
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'#': fileURLToPath(new URL('./src', import.meta.url))
}
},
optimizeDeps: {
exclude: ['highcharts'],
}
})
babel.config.js
module.exports = {
presets: [
'#vue/cli-plugin-babel/preset'
]
}
I think the cause of the issue is this config:
optimizeDeps: {
exclude: ['highcharts'], // ❌ don't do this
}
The solution would be to remove highcharts from optimizeDeps.exclude.
Also, you don't need a Babel config when using Vite. That might be another source of the problem.
demo
Here's a working example of vue3 + highcharts-vue: https://codesandbox.io/s/vue3-highcharts-example-k98kyz
Be sure to update to the latest versions, and to use babel or any other transpilers to work with ESM packages.

Why am I getting "Cannot find module..." Typescript error for ".vue" file on webpack-dev-server recompilation?

I've setup a small webpack project which creates a Vue app bundle which is included in a static HTML file where the app is injected. I want to have components written in Typescript so I've included ts-loader in the webapck configuration. The build process - using the "webpack" command - works ok, but I'm having some trouble when I use webpack-dev-server.
When I initially start the server, everything works fine: the bundle is created and served on my local server and the browser displays the app correcly. However, when I make a change in the source code and save, I get a Typescript error when the code is recompiled telling me that a module or declaraton is missing for the ".vue" file for my component:
TS2307: Cannot find module './components/Banner.vue' or its corresponding type declarations.
To start the server I use the following command:
webpack serve --open
Project's folder structure
=======
webpack.config.js
const { VueLoaderPlugin } = require('vue-loader')
const path = require('path')
module.exports = {
mode: 'development',
devtool: 'inline-source-map',
entry: {
app: './src/app.js',
},
output: {
filename: '[name].bundle.js',
},
plugins: [
new VueLoaderPlugin(),
],
devServer: {
contentBase: path.join(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.vue$/,
use: ['vue-loader']
},
{
test: /\.ts$/,
loader: 'ts-loader',
exclude: [/node_modules/],
options: { appendTsSuffixTo: [/\.vue$/] }
},
],
},
}
app.js
import Vue from 'vue'
import App from './App.vue'
const app = new Vue({
render: (h) => h(App)
})
app.$mount('#app')
App.vue
<template>
<div id="app">
<h1>{{ welcomeMessage }}</h1>
<Banner />
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import Banner from './components/Banner.vue'
export default Vue.extend({
components: {
Banner,
},
data: () => ({
welcomeMessage: 'Hello world!'
})
})
</script>
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"strict": true,
"module": "es2015",
"moduleResolution": "node"
}
}
#types/vue-shims.d.ts
declare module "*.vue" {
import Vue from 'vue'
export default Vue
}
package.json
{
"name": "2021-06-21-webpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack",
"dev": "webpack serve --open"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"ts-loader": "^8.3.0",
"typescript": "^4.3.4",
"vue-loader": "^15.9.7",
"vue-template-compiler": "^2.6.14",
"webpack": "^4.46.0",
"webpack-cli": "^4.7.2",
"webpack-dev-server": "^3.11.2"
},
"dependencies": {
"vue": "^2.6.14"
}
}

vue.runtime.esm-browser.js does not render Vue 3 components

I created a vue 3 project using Vue cli. I am using a webpack config to manage my build. When I point my vue bundle to vue.runtime.esm-browser.js, then I get a warning in browser console. "[Vue warn]: Component provided template option but runtime compilation is not supported in this build of Vue. Use "vue.esm-browser.js" instead."
When I checked the docs, it was mentioned as "vue-loader" plugin converts the html template to render functions. Looks like I am missing something which is needed to webpack.
Entry file : main.js
import { createApp } from "vue";
import corecomponentA from "../core/components/corecomponentA.vue";
createApp({
components: {
"core-component-a": corecomponentA,
},
}).mount("#app");
Webpack.config.js
var path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const { VueLoaderPlugin } = require("vue-loader");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin;
const WebpackBar = require("webpackbar");
module.exports = (env, options) => {
const devMode = options.mode != "production";
return {
entry: {
"vue-bundle-store": "./src/entry/main.js",
},
output: {
path: path.resolve(
__dirname,
"./../ui.clientlibs/src/js/"
),
filename: "[name].js",
chunkFilename: "[name].js",
publicPath: process.env.BASE_URL,
},
module: {
rules: [
{
enforce: "pre",
test: /\.js$/,
exclude: /node_modules/,
loader: "eslint-loader",
},
{
test: /\.vue$/,
loader: "vue-loader",
},
{
test: /\.js$/,
loader: "babel-loader",
exclude: "/node_modules/",
query: {
presets: ["#babel/preset-env"],
},
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader",
options: { babelrc: true },
},
{
loader: "ts-loader",
options: { appendTsSuffixTo: [/\.vue$/] },
},
],
},
],
},
stats: {
colors: true,
},
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: "vendor-bundle",
chunks: "all",
},
},
},
minimizer: !devMode
? [
new UglifyJsPlugin({
sourceMap: false,
uglifyOptions: {
chunkFilter: (chunk) => {
if (chunk.name === "vendor-bundle") {
return false;
}
return true;
},
compress: {
drop_console: true,
},
mangle: {
reserved: ["vueIns", "args", "el"],
},
},
}),
]
: [],
},
devtool: "source-map",
plugins: [
new CleanWebpackPlugin(),
new VueLoaderPlugin(),
new WebpackBar(),
new BundleAnalyzerPlugin({
analyzerPort: 4000,
openAnalyzer: false,
analyzerMode: "static",
}),
] ,
resolve: {
extensions: [".ts", ".js", ".vue", ".json"],
alias: {
vue: devMode ? "vue/dist/vue.runtime.esm-browser.js" : "vue/dist/vue.runtime.esm-browser.prod.js"
}
}
};
};
coreComponentA.vue
<script lang="ts">
import { h, ref, reactive } from "vue";
export default {
setup() {
const str = ref("Core component B");
const object = reactive({ foo: "bar" });
return () => h("div", [str.value, object.foo]);
}
};
</script>
package.json
{
"name": "vue3.test",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit",
"lint": "vue-cli-service lint",
"analyze-bundle": "webpack-bundle-analyzer stats.json",
"bundle": "webpack --mode=production --env.production --config webpack.config.js",
"bundle-dev": "webpack --mode=development --env.production=false --config webpack.config.js",
"stats": "webpack --mode=production --env.production --config webpack.config.js --profile --json > stats.json"
},
"dependencies": {
"vue": "^3.0.2"
},
"devDependencies": {
"#types/jest": "^24.0.19",
"#typescript-eslint/eslint-plugin": "^2.33.0",
"#typescript-eslint/parser": "^2.33.0",
"#vue/cli-plugin-babel": "~4.5.0",
"#vue/cli-plugin-eslint": "~4.5.0",
"#vue/cli-plugin-typescript": "~4.5.0",
"#vue/cli-plugin-unit-jest": "~4.5.0",
"#vue/cli-service": "~4.5.0",
"#vue/compiler-sfc": "^3.0.2",
"#vue/eslint-config-prettier": "^6.0.0",
"#vue/eslint-config-typescript": "^5.0.2",
"#vue/test-utils": "^2.0.0-0",
"clean-webpack-plugin": "^3.0.0",
"core-js": "^3.6.5",
"eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.1.3",
"eslint-plugin-vue": "^7.0.0-0",
"html-webpack-plugin": "^3.2.0",
"prettier": "^1.19.1",
"typescript": "~3.9.3",
"uglifyjs-webpack-plugin": "^2.2.0",
"vue-jest": "^5.0.0-0",
"vue-loader": "^16.0.0-beta.8",
"webpack-cli": "^3.3.10",
"webpackbar": "^4.0.0"
}
}
babel.config.js
module.exports = {
ignore: [/\/core-js/],
presets: [
[
"#babel/preset-env",
{ modules: false, useBuiltIns: "usage", corejs: "3.6.5" },
],
],
overrides: [
{
test: "./node_modules",
sourceType: "unambiguous",
},
],
};
Usage of my component in a html file
<div id="app">
<core-component-a></core-component-a>
</div>
The component is not rendered in browser. Instead the below message is displayed.
VM211871:1 [Vue warn]: Component provided template option but runtime compilation is not supported in this build of Vue. Use "vue.esm-browser.js" instead.
at <App>
vue-loader converts the html template to render function only in SFC's (Sinle File Components) - .vue files (as you can tell from vue rule in Webpack config) - and only templates provided in <template></template> block of SFC
But you have a template in your HTML file - content of <div id="app"> is essentially Vue template. Runtime + Compiler vs. Runtime-only
Docs vue.esm-bundler.js: includes the runtime compiler. Use this if you are using a bundler but still want runtime template compilation (e.g. in-DOM templates or templates via inline JavaScript strings - component template option).
Also if you using Webpack, you should use "bundler" version of Vue
Webpack.config.js
alias: {
vue: "vue/dist/vue.esm-bundler.js"
}
...you don't need to switch minified/dev bundle because Webpack will (when configured correctly) optimize Vue code same way as your own code..
Also, pay attention to this sentence in the docs: Leaves prod/dev branches with process.env.NODE_ENV guards (must be replaced by bundler)
NODE_ENV is conventionally used to define the environment type and is used by Vue to decide what code to include...
Note
I don't really understand why are You using your own Webpack config for project created with Vue CLI when whole point of Vue CLI is to manage webpack config for you and offers plenty of options to customize it...doesn't make any sense
If you are using Vite, add the alias 'vue': 'vue/dist/vue.esm-bundler' to vite.config.js
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'vue': 'vue/dist/vue.esm-bundler',
},
}
})
you just have to replace on Webpack.config.js
alias: {
vue: devMode ? "vue/dist/vue.runtime.esm-browser.js" : "vue/dist/vue.runtime.esm-browser.prod.js"
}
With
vue: "vue/dist/vue.esm-bundler.js"
This works for me.

vue.js - dynamic imports results in error: Support for the experimental syntax 'dynamicImport' isn't currently enabled

I'm learning Vue.js with Webpack for the first time today and trying to get a router working with lazy/dynamic imports.
I want to use lazy/dynamic imports because I am rebuilding my content management system which has many, many pages that may or may not be used during the user's session, so loading the modules they need dynamically, when they need them, makes more sense with regards to my application.
My very basic router currently looks like this:
import Vue from "vue";
import Router from "vue-router";
Vue.use(Router);
function loadView(view) {
return () => import(/* webpackChunkName: "view-[request]" */ `#/views/${view}.vue`);
}
export default new Router({
routes: [
{
path: "/",
name: "dashboard",
component: loadView("Dashboard")
},
{
path: "/login",
name: "login",
component: loadView("Login")
}
]
});
However, I run into the following compilation error:
ERROR in ./src/router/index.js Module build failed (from
./node_modules/babel-loader/lib/index.js): SyntaxError:
...../src/router/index.js: Support for the experimental syntax
'dynamicImport' isn't currently enabled
With the additional note:
Add #babel/plugin-syntax-dynamic-import to the
'plugins' section of your Babel config to enable parsing.
And shows me which line is the problem, which is quite obvious anyway:
return () => import(/*..........
^
I recognise this error from when I was playing with Webpack on its own a few months ago, so I knew I had to install the dynamic import plugin to make this work.
This is what I installed:
npm install babel-plugin-syntax-dynamic-import
And I made this plugin available in my babel.rc configuration file and ran npm run dev to recompile everything:
{
"presets": [
[
"#babel/env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}
]
],
"plugins": ["#babel/plugin-syntax-dynamic-import"]
}
But I'm still getting the error and I still can't use dynamic importing features! Am I doing something wrong? Has anybody else had trouble with getting dynamic imports to work?
My webpack.config file:
'use strict';
const webpack = require('webpack');
const path = require('path');
const { VueLoaderPlugin } = require('vue-loader');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
mode: 'development',
entry: [
'./src/app.js'
],
devServer: {
hot: true,
watchOptions: {
poll: true
}
},
module: {
rules: [
{
test: /\.vue$/,
use: 'vue-loader'
},
{
test: /\.js$/,
use: 'babel-loader'
},
{
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
sourceMap: true,
outputStyle: 'compressed',
data: `
#import "./src/assets/scss/_variables.scss";
#import "./src/assets/scss/_mixins.scss";
`
}
}
]
}
]
},
resolve: {
alias: {
"#": path.resolve(__dirname, './src'),
"Components": path.resolve(__dirname, './src/components/')
}
},
optimization: {
minimizer: [new UglifyJsPlugin()],
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
})
]
}
My package.json file:
{
"name": "manage_v2",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --config build/webpack.config.dev.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^0.18.0",
"vue": "^2.5.22",
"vue-router": "^3.0.2",
"vuex": "^3.1.0"
},
"devDependencies": {
"#babel/core": "^7.2.2",
"#babel/plugin-syntax-dynamic-import": "^7.2.0",
"#babel/preset-env": "^7.3.1",
"babel-loader": "^8.0.5",
"babel-plugin-dynamic-import-webpack": "^1.1.0",
"css-loader": "^2.1.0",
"html-webpack-plugin": "^3.2.0",
"node-sass": "^4.11.0",
"sass-loader": "^7.1.0",
"uglifyjs-webpack-plugin": "^2.1.1",
"vue-loader": "^15.6.2",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.5.22",
"webpack": "^4.29.0",
"webpack-cli": "^3.2.1",
"webpack-dev-server": "^3.1.14"
}
}
I fixed the problem myself after many hours of frustration. I still don't know why the method that's used in the Babel, Webpack and Vue documentation doesn't work but I did get this working:
I first removed the plugin declaration from babel.rc file and then added an option to the babel loader in webpack.config file:
{
test: /\.js$/,
use: {
loader: "babel-loader",
options: {
plugins: [
"#babel/plugin-syntax-dynamic-import"
]
}
}
}
I hope this helps others.
You have the wrong plugin assignment:
"plugins": ["#babel/plugin-syntax-dynamic-import"]
Would be the correct format for that plugin.