vue3, vite and vue-router#next, cannot resolve component router-view - vue.js

I created a project using Vite and added vue-router#next. I am using the router inside of the main.js as I've browsed around and seemed like this was the problem, however it does not fix the issue I am having.
// package.json
{
"name": "rng-alpha",
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview"
},
"dependencies": {
"vue": "^3.0.5",
"vue-router": "^4.0.5"
},
"devDependencies": {
"#vitejs/plugin-vue": "^1.1.5",
"#vue/compiler-sfc": "^3.0.7",
"vite": "^2.0.5"
}
}
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import router from './router/router';
const app = createApp(App);
app.use(router);
app.mount('#app');
// router.js
import {
createWebHistory,
createRouter
} from 'vue-router'
import Home from '../components/Home.vue'
const routes = [{
path: "/",
name: "Home",
component: Home
}]
const router = createRouter[{
history: createWebHistory,
routes,
}]
export default router
// App.vue
<template>
<div>
<div>hi</div>
<router-view />
</div>
</template>
The warnings I am getting are the following:
How can I make the router-view work? Since I am not able to utilize it right now.

createRouter is a method that should be called using () not [] :
const router = createRouter({
history: createWebHistory,
routes,
})

Related

Uncaught ReferenceError: module is not defined, laravel, vue-router

Trying to import some routes for a Vue3, VueRouter instance in Laravel9, Vite only receive the above error. Here's my config:-
package.json
"dependencies": {
"vue": "^3.2.45",
"vue-router": "^4.1.6",
"vuex": "^4.1.0"
}
resources/js/routes.js
module.exports = [
{
path: '/',
name: 'posts.index',
component: () => import('./routes/Posts/Index.vue')
},
{
path: '/post/:slug',
name: 'posts.show',
component: () => import('./routes/Posts/Show.vue')
}
]
resources/js/app.js
import './bootstrap';
import * as Vue from 'vue';
import * as VueRouter from 'vue-router';
import * as Vuex from 'vuex';
import * as routes from './routes';
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes: routes
// routes: import('./routes.js')
})
help

Vue test utils for Vue3 : document is not defined

I try to bootstrap a simple app based on the following Vue3, Vite, Vitest
I also installed the vue 3 compatible version of vue test utils to test vue components.
I have an error trying to replicate the basic example in the docs :
import { mount } from "#vue/test-utils";
import { expect, test } from 'vitest'
// The component to test
const MessageComponent = {
template: "<p>{{ msg }}</p>",
props: ["msg"],
};
test("displays message", () => {
const wrapper = mount(MessageComponent, {
props: {
msg: "Hello world",
},
});
// Assert the rendered text of the component
expect(wrapper.text()).toContain("Hello world");
});
FAIL src/tests/hello-world.test.ts > displays message
ReferenceError: document is not defined
❯ Proxy.mount node_modules/#vue/test-utils/dist/vue-test-utils.cjs.js:7840:14
7838| addToDoNotStubComponents(component);
7839| registerStub({ source: originalComponent, stub: component });
7840| var el = document.createElement('div');
| ^
7841| if (options === null || options === void 0 ? void 0 : options.attachTo) {
7842| var to = void 0;
Re-running tests... [ src/tests/hello-world.test.ts ]
My package.json
{
"name": "vite-vue3-poc",
"version": "0.0.0",
"scripts": {
"serve": "vite preview",
"build": "vite build",
"coverage": "vitest --coverage",
"dev": "vite",
"preview": "vite preview",
"test": "vitest"
},
"dependencies": {
"#mdi/font": "5.9.55",
"prettier": "^2.5.1",
"roboto-fontface": "*",
"vue": "^3.2.25",
"vuetify": "^3.0.0-alpha.0",
"webfontloader": "^1.0.0"
},
"devDependencies": {
"#vitejs/plugin-vue": "^2.0.0",
"#vue/cli-plugin-babel": "5.0.0-beta.7",
"#vue/cli-service": "5.0.0-beta.7",
"#vue/test-utils": "^2.0.0-rc.18",
"#vuetify/vite-plugin": "^1.0.0-alpha.3",
"sass": "^1.38.0",
"sass-loader": "^10.0.0",
"vite": "^2.7.2",
"vitest": "^0.1.23",
"vue-cli-plugin-vuetify": "~2.4.5",
"vuetify-loader": "^2.0.0-alpha.0"
}
}
vite.config.js
import { defineConfig } from "vite";
import vue from "#vitejs/plugin-vue";
import vuetify from "#vuetify/vite-plugin";
import path from "path";
/// <reference types="vitest" />
// Configure Vitest (https://vitest.dev/config)
// https://vitejs.dev/config/
export default defineConfig({
test: {
/* for example, use global to avoid globals imports (describe, test, expect): */
// globals: true,
},
plugins: [
vue(),
// https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vite-plugin
vuetify({
autoImport: true,
}),
],
define: { "process.env": {} },
resolve: {
alias: {
"#": path.resolve(__dirname, "src"),
},
},
});
Finally fixed it by manually installing jsdom and declaring it in vite.config.ts
export default defineConfig({
test: {
globals: true,
environment: "jsdom",
},
...
}
Like others have pointed out, you need to set environment: 'jsdom' in vitest.config.ts. Alternatively, you could set environment: 'happy-dom'.
In the example provided by the Vitest documentation, they used to use happy-dom instead of jsdom. From what I gather, happy-dom is a faster alternative to jsdom. I'm using happy-dom in my project, and I'm happy with it! :)
EDIT: I changed my wording to reflect the fact that the Vitest example used to use happy-dom. As of this writing, it uses jsdom.
No need to install jsdom manually. By setting environment: "jsdom" in the test property, Vitest automatically asks you if you want to install it.
This config helped me
Your vite.config.ts
import { fileURLToPath, URL } from "node:url"
import { defineConfig } from "vite"
import type { UserConfig as VitestUserConfigInterface } from "vitest/config"
import vue from "#vitejs/plugin-vue"
const vitestConfig: VitestUserConfigInterface = {
test: {
globals: true,
environment: "jsdom",
},
}
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
"#": fileURLToPath(new URL("./src", import.meta.url)),
},
},
test: vitestConfig.test,
})

How to add Router to #vue/cli app with vuejs 3?

Learning vuejs3 I created new #vue/cli app with command
vue create myapp
with vuejs 3 selected
I added Router to my project and added Router reference in my src/main.js :
import { createApp } from 'vue'
import { createRouter/*, createWebHistory */ } from 'vue-router'
import WelcomeScreen from './pages/WelcomeScreen.vue'
import UsersList from './pages/UsersList.vue'
import App from './App.vue'
const router = createRouter({
// history: createWebHistory(),
mode: 'history',
routes: [
{ path: '/', component: WelcomeScreen },
{ path: '/users', component: UsersList }
]
})
const app = createApp(App)
app.use(router)
app.mount('#app')
But In the console I see warning :
"export 'createRouter' was not found in 'vue-router'
and error :
main.js?56d7:10 Uncaught TypeError: Object(...) is not a function
In my package.json I have :
"dependencies": {
"core-js": "^3.6.5",
"mitt": "^2.1.0",
"vue": "^3.0.0",
"vue-router": "^3.4.8"
},
and
$ vue --version
#vue/cli 4.5.8
Which way is valid?
Also are some some vuejs3 tutorials for #vue/cli?
I found some vuejs 3 tutorials, but not for #vue/cli and that raise some confusion...
Say in my #vue/cli with vue2 I use file src/router/index.js, but I do not remember if
I have created manually...
Thanks!
You need install vue-router like this for vue3:
npm install vue-router#next --save
Router.js
import { createApp } from 'vue'
import App from './App.vue'
import { createRouter, createWebHistory } from "vue-router"
const routeInfos = [
{
path : "/",
component : HomePage
},
{
path : "/favorites",
component : FavoritesPage
}
]
const router = createRouter({
history : createWebHistory(),
routes : routeInfos
})
export default router;
import In Main.js
import router from "./router"
createApp(App).use(router).mount('#app')
I had the same problem and found the answer here
// uninstall vue2.x vue-router
npm uninstall vue-router --save
// install vue3 vue-router
npm install vue-router#next --save

[Vue warn]: Unknown custom element: <nuxt-link> - When running jest unit tests

Problem
I'm using nuxt 1.4 with routing using Jest to do unit testing. My application doesn't throw errors and seems to work perfectly. However when running my unit test npm run unit (which runs jest) it throws an error in the terminal: [Vue warn]: Unknown custom element: <nuxt-link> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
Expected
I would expect it to not throw this error since my application is working.
Files
package.json:
{
"name": "vue-starter",
"version": "1.0.0",
"description": "Nuxt.js project",
"private": true,
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
"precommit": "npm run lint",
"test": "npm run lint && npm run unit",
"unit": "jest",
"unit:report": "jest --coverage"
},
"dependencies": {
"babel-jest": "^22.4.1",
"jest-serializer-vue": "^1.0.0",
"node-sass": "^4.7.2",
"npm": "^5.7.1",
"nuxt": "^1.0.0",
"sass-loader": "^6.0.7",
"vue-jest": "^2.1.1"
},
"devDependencies": {
"#vue/test-utils": "^1.0.0-beta.12",
"babel-eslint": "^8.2.1",
"eslint": "^4.15.0",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.7.1",
"eslint-plugin-vue": "^4.0.0",
"jest": "^22.4.2"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
],
"jest": {
"moduleFileExtensions": [
"js",
"vue"
],
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/babel-jest",
".*\\.(vue)$": "<rootDir>/node_modules/vue-jest"
},
"snapshotSerializers": [
"<rootDir>/node_modules/jest-serializer-vue"
]
}
}
The component that I test:
<template>
<div>
<nuxt-link class="name" :to="{ path: `entity/${item.id}`, params: { id: item.id }}">{{item.name}}</nuxt-link>
<button class="connect" #click="connect">{{ btnText }}</button>
</div>
</template>
<script>
// import nuxtLink from '../.nuxt/components/nuxt-link';
const connectionStatusMap = [
'Connect',
'Connected',
'Pending',
'Cancel',
];
export default {
/*components: {
'nuxt-link': nuxtLink,
},*/
props: {
item: {
type: Object
}
},
...
}
</script>
My test script:
import TestItem from '../components/TestItem';
import { shallow, mount, createLocalVue } from '#vue/test-utils';
import Vuex from 'vuex';
import VueRouter from 'vue-router';
const localVue = createLocalVue()
localVue.use(Vuex)
localVue.use(VueRouter)
...
it(`should show the entity`, () => {
const wrapper = mount(TestItem, {
propsData: { item },
localVue,
store,
// stubs: ['nuxt-link'],
})
expect(wrapper.find('.name').text()).toBe(item.name);
});
it(`should show allow me to connect if I'm not yet connected`, () => {
const wrapper = shallow(TestItem, {
propsData: { item },
localVue,
store,
stubs: ['nuxt-link'],
})
expect(wrapper.find('.connect').text()).toBe('Connect');
});
...
I tried
I tried creating a localVue and also stubbing the component as suggested in this github comment
I also tried shallow/mount but that did not seem to work either.
This is how I was able to get rid of the annoying warning:
Include RouterLinkStub, eg.:
import { shallowMount, createLocalVue, RouterLinkStub } from '#vue/test-utils';
Map NuxtLink stub to RouterLinkStub
const wrapper = shallowMount(TestItem, {
...
stubs: {
NuxtLink: RouterLinkStub
}
})
And in case you were checking nuxt-link text or something, change:
const link = wrapper.find('nuxt-link');
to
const link = wrapper.find(RouterLinkStub);
Found this gold on https://onigra.github.io/blog/2018/03/19/vue-test-utils-router-link-stub/
Good thing you don't need to know japanese to read code...
Although the answers provided could work. What I ended up using was based on this guide
const wrapper = mount(TestItem, {
propsData: { item },
localVue,
store,
stubs: {
NuxtLink: true,
// Any other component that you want stubbed
},
});
I managed to get it working using this workaround for Storybook:
import { mount, createLocalVue } from '#vue/test-utils'
import Component from '#/components/Component.vue'
const localVue = createLocalVue()
localVue.component('nuxt-link', {
props: ['to'],
template: '<slot>NuxtLink</slot>',
})
describe('Test Component', () => {
const wrapper = mount(Component, {
stubs: ['nuxt-link'],
localVue
})
})
I added below lines of code to get this working.
In your test file
import NuxtLink from "path to nuxt-link.js"
Mycomponent.components.NuxtLink = NuxtLink
In your jest conf file
transformIgnorePatterns: [
"path to nuxt-link.js"
],
Or you could add below line in mount options
mount(Mycomponent, {stubs: ["nuxt-link"]})
I have:
// path: ./test/jest.setup.js
import Vue from 'vue'
import VueTestUtils from '#vue/test-utils'
// Mock Nuxt components
VueTestUtils.config.stubs['nuxt-link'] = '<a><slot /></a>'
VueTestUtils.config.stubs['no-ssr'] = '<span><slot /></span>'
and
// path: ./jest.config.js
module.exports = {
// ... other stuff
setupFilesAfterEnv: ['./test/jest.setup.js']
}
... and this solves all my jest test in the nuxt app
To anyone getting the Unknow custom element: <router-link>
My issue was, I used mount instead of shallow when creating the component.
shallow usage:
Like mount, it creates a Wrapper that contains the mounted and
rendered Vue component, but with stubbed child components.
Source: https://vue-test-utils.vuejs.org/en/api/shallow.html
Here is a working example
import { shallow } from '#vue/test-utils';
import ContentCard from '../../components/ContentCard.vue';
import NuxtLink from '../../.nuxt/components/nuxt-link';
const createComponent = propsData => shallow(ContentCard, { propsData });
describe('ContentCard', () => {
let component;
beforeEach(() => {
ContentCard.components = ContentCard.components || {};
ContentCard.components.NuxtLink = NuxtLink;
});
describe('Properties', () => {
it('has an imgSrc property', () => {
component = createComponent({ imgSrc: 'X' });
expect(component.props().imgSrc).toBe('X');
});
});
});
...
import NuxtLink from '../.nuxt/components/nuxt-link.js'
...
TestItem.components = TestItem.components || {};
TestItem.components.NuxtLink = NuxtLink;
const wrapper = shallow(TestItem, {
...
});
...
// test/jestSetup.js
import Vue from 'vue'
import Vuetify from 'vuetify'
import { config } from '#vue/test-utils'
Vue.use(Vuetify)
config.stubs.NuxtLink = { template: '<a><slot /></a>' }

Publish a react component to npm and reuse it

I am trying to publish a basic React component to my npm registry and trying to reuse it. I think I am not following proper way to distribute my react component. Here's what I have:
This is the directory structure:
MyReactPOC
-> main.jsx
-> .npmrc
-> package.json
-> webpack.config.js
main.jsx
import React from 'react';
class MyComponent extends React.Component {
render() {
return (
<div>
<p>Hello from MyComponent!!</p>
</div>
);
}
}
export default MyComponent
package.json
{
"name": "#pankaj/my-component",
"version": "1.0.7",
"description": "POC for importing a component",
"main": "./dist/bundle.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"prepublish": "webpack --config webpack.config.js"
},
"repository": {
"type": "git",
"url": "my git repo"
},
"author": "Pankaj",
"license": "ISC",
"dependencies": {
"react": "~15.5.4",
"react-dom": "~15.5.4"
},
"devDependencies": {
"babel-cli": "~6.24.1",
"babel-core": "~6.24.1",
"babel-loader": "~6.4.1",
"babel-preset-es2015": "~6.24.1",
"babel-preset-react": "~6.24.1",
"webpack": "~2.4.1"
}
}
webpack.config.js
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: './main.jsx',
output: { path: path.join(__dirname, 'dist'), filename: 'bundle.js' },
module: {
loaders: [
{
test: /.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
}
]
},
};
I import the module in another project using import MyComponent from '#pankaj/my-component'.
When I use this component like
I get the following error:
React.createElement: type is invalid -- expected a string (for
built-in components) or a class/function (for composite components)
but got: object. You likely forgot to export your component from the
file it's defined in.
Please help me understand the right way to distribute the react components so that they can be used by other projects within my org.
Here is how I use this component:
ComponentUse.js
import React from 'react';
import ReactDOM from 'react-dom';
import MyComponent from '#pankaj/my-component';
ReactDOM.render(
<MyComponent/>,
document.getElementById('root')
);
I have an index.html that has the 'root' div.
Every react component needs a return statement. Add a return statement in your render function and it should work.
...
render() {
return (<div>...</div>)
}
You cannot directly render to the Dom from your react component, instead return it so that react can work with it.
In webpack, specify your output file as a library using output.library https://webpack.js.org/concepts/output/#output-library
I wrote a full Medium story because I had the same issue as you and there is no information about it.
Check it out: https://medium.com/#BrodaNoel/how-to-create-a-react-component-and-publish-it-in-npm-668ad7d363ce
The main fix is to add libraryTarget: 'umd' in the webpack.config.js file
If you export with es6 syntax with babel, your component will be in MyComponent.default namespace. To avoid this you should install:
npm i --save-dev babel-plugin-add-module-exports in your .babelrc?
and add it to the babel conf:
{
"presets": [ "es2015", "react"],
"plugins": ["add-module-exports"]
}