dynamic sitemap generator in vue js project - vue.js

i want to generate sitemap based on routes in vue js project but i could not find any solution for this?
i found vue-router-sitemap package in npm but it did not mention any example and i totally confused? what is the solution for this?
anyway is there any way to access routes object in another normal js file ?
this is the xample of that but what is the app! and how can i use these?
// sitemapMiddleware.js
import VueRouterSitemap from 'vue-router-sitemap';
import path from 'path';
import { router } from 'router';
export const sitemapMiddleware = () => {
return (req, res) => {
res.set('Content-Type', 'application/xml');
const staticSitemap = path.resolve('dist/static', 'sitemap.xml');
const filterConfig = {
isValid: false,
rules: [
/\/example-page/,
/\*/,
],
};
new VueRouterSitemap(router).filterPaths(filterConfig).build('http://example.com').save(staticSitemap);
return res.sendFile(staticSitemap);
};
};
app.get('/sitemap.xml', sitemapMiddleware());

This middleware should place in vue.config.js.

Related

Access Nuxt custom plugin from Composition API

I am using VueClipboard in my nuxt project.
https://www.npmjs.com/package/vue-clipboard2
I have a plugin file vue-clipboard.js
import Vue from "vue";
import VueClipboard from 'vue-clipboard2';
Vue.use(VueClipboard);
It is imported into nuxt.config
plugins: ['#/plugins/vue-clipboard'],
This sets up a global variable $copyText and in nuxt without the composition API I can do something like
methods: {
async onCopyCodeToClipboard() {
const code = 'code'
await this.$copyText(code)
},
},
However inside the setup using the composition API (#nuxtjs/composition-api) when I write a function I do not have access to this.$copyText
const onCopyCodeToClipboard = async () => {
const code = context.slots.default()[0].elm.outerHTML
// -> Can't use this here - await this.$copyText(code)
}
So how do I make $copyText available to use inside the composition API?
I was able to get this to work via the Nuxt useContext() method:
import { useContext } from '#nuxtjs/composition-api'
export default function () {
const { $copyText } = useContext();
$copyText('code');
}

TypeError: bodyParser.json is not a function in nuxt.js

I have received an error message stating: TypeError: bodyParser.json is not a function. My nuxt.config.js file has the following details regarding bodyparser (I originally had const bodyParser = require('body-parser') but an error appeared telling me that I had to use 'import' instead of 'require' so I changed it to 'import('body-parser'):
const bodyParser = import('body-parser')
export default {
serverMiddleware: [
bodyParser.json(),
'~/api'
]
}
In my index.js file under the api folder, I have the following code:
const express = require('express')
const bodyParser = require('body-parser')
const router = express.Router()
const app = express()
router.use((req, res, next) => {
Object.setPrototypeOf(req, app.request)
Object.setPrototypeOf(res, app.response)
req.res = res
res.req = req
next()
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
})
router.post('/track-data', (req, res) => {
console.log('Stored data!', req.body.data)
res.status(200).json({ message: 'Success!' })
})
module.exports = {
path: '/api',
handler: router
}
Does anyone know how to get this to run? Everytime I enter 'npm run dev' in the terminal, I get the error 'TypeError: bodyParser.json is not a function'.
I had a slightly similar issue and could solve it with this code, first i imported express in the config file, before i did it like you, with bodyParser, but got a deprecated warning, then i use it in the api folder, in the index file, like so:
// nuxt.config.js
import express from 'express';
export default {
ssr: true,
.......,
.......,
serverMiddleware: [
express.json(),
// Api middleware
{ path: '/api', handler: '~/api/index.js' },
]
}
// ~/api/index.js
// Router setup for serverMiddleware
router.use((req, res, next) => {
Object.setPrototypeOf(req, app.request);
Object.setPrototypeOf(res, app.response);
req.res = res;
res.req = req;
next();
});
export default {
path: '/api',
handler: router
};
hope it helps ! 👍
I'm not familiar with nuxtjs specifically, but after looking at the nuxtjs module export docs it looks like your require inside your index.js should be a path to the file, rather than just the string body-parser which I have to imagine just gets processed something like an npm module if no path is supplied.
Additionally, at least in NodeJS and per the MDN docs on export and import, the syntax to import something that's exported with export default is import { destructuredModuleName } from 'string/representing/relative/or/absolute/path/to/module'
or
import * as whatYouWantToCallTheObject from 'string/representing/relative/or/absolute/path/to/module' would give you a more traditional module object with properties/methods matching properties on the exported module.
This should fix it:
import bodyParser from 'body-parser'
You actually used the import() as a dynamic import. It returned a promise which didn't have the json property. Therefore, the error was displayed.

How to mock modules in storybook's stories?

I have a Vue component which includes some external modules with complicated logic. For example:
// Component.vue
import Vue from 'vue';
import { externalModule } from '#/path/to/module';
export default {
methods: {
useExternalModule() {
externalModule.doSomethig();
}
}
};
Is it possible to mock the externalModule inside the story?
I'm using Storybook v6.
You can create a __mocks__ folder to put your mock components in. Then in your .storybook/main.js file use this to point webpack to your mock file.
module.exports = {
// your Storybook configuration
webpackFinal: (config) => {
config.resolve.alias['externalModule'] = require.resolve('../__mocks__/externalModule.js');
return config;
},
};
This is covered in the docs under "Mocking imports".
However, this is a global configuration and not a story level configuration.

How to initialize manually next.js app (for testing purpose)?

I try to test my web services, hosted in my Next.js app and I have an error with not found Next.js configuration.
My web service are regular one, stored in the pages/api directory.
My API test fetches a constant ATTACKS_ENDPOINT thanks to this file:
/pages/api/tests/api.spec.js
import { ATTACKS_ENDPOINT } from "../config"
...
describe("endpoints", () => {
beforeAll(buildOptionsFetch)
it("should return all attacks for attacks endpoint", async () => {
const response = await fetch(API_URL + ATTACKS_ENDPOINT, headers)
config.js
import getConfig from "next/config"
const { publicRuntimeConfig } = getConfig()
export const API_URL = publicRuntimeConfig.API_URL
My next.config.js is present and is used properly by the app when started.
When the test is run, this error is thrown
TypeError: Cannot destructure property `publicRuntimeConfig` of 'undefined' or 'null'.
1 | import getConfig from "next/config"
2 |
> 3 | const { publicRuntimeConfig } = getConfig()
I looked for solutions and I found this issue which talks about _manually initialise__ next app.
How to do that, given that I don't test React component but API web service ?
I solved this problem by creating a jest.setup.js file and adding this line of code
First add jest.setup.js to jest.config.js file
// jest.config.js
module.exports = {
// Your config
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
};
AND then
// jest.setup.js
jest.mock('next/config', () => () => ({
publicRuntimeConfig: {
YOUR_PUBLIC_VARIABLE: 'value-of-env' // Change this line and copy your env
}
}))
OR
// jest.setup.js
import { setConfig } from 'next/config'
import config from './next.config'
// Make sure you can use "publicRuntimeConfig" within tests.
setConfig(config)
The problem I faced with testing with Jest was that next was not being initialized as expected. My solution was to mock the next module... You can try this:
/** #jest-environment node */
jest.mock('next');
import next from 'next';
next.mockReturnValue({
prepare: () => Promise.resolve(),
getRequestHandler: () => (req, res) => res.status(200),
getConfig: () => ({
publicRuntimeConfig: {} /* This is where you import the mock values */
})
});
Read about manual mocks here: https://jestjs.io/docs/en/manual-mocks
In my case, I had to:
Create a jest.setup.js file and
setConfig({
...config,
publicRuntimeConfig: {
BASE_PATH: '/',
SOME_KEY: 'your_value',
},
serverRuntimeConfig: {
YOUR_KEY: 'your_value',
},
});
Then add this in your jest.config.js file:
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],

Nuxt + Vue + Axios + Enviroment Variables

I am unable to provide axios a baseUrl using an enviroment variable
I am using nuxt/vue/axios
What I have is roughly:
// axios.js
import Vue from 'vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
axios.defaults.baseURL = process.env.BASE_URL
Vue.use(VueAxios, axios)
and
// index.vue (front page as it appears on the client)
populateFilters () {
Vue.axios.get('filters').then((response) => {
this.$store.commit('data/filters', response.data)
})
.catch((e) => {
console.error(e)
})
}
and inside nuxt.config.js
// nuxt.config.js
build: {
extractCSS: true,
extend (config, ctx) {
// Run ESLint on save
const envLoad = require('dotenv').config()
if (envLoad.error){
throw result.error
}
}
},
console.log(process.env.BASE_URL) prints the correnct connection string in CMD, however, in chrome web browser it outputs "undefined" and I get the following error
GET http://localhost:3000/filters 404 (Not Found)
meaning that axios (probably) defaults to http://localhost:3000 whenever the baseUrl for axios has not been set.
What I think the problem is
The server/client pair that is loaded up by nuxt has different contexts or that the server loads up axios before the enviroment variables have been loaded
What I need
I need to be able to either:
create .env files that contains (amongst other things) the BASE_URL
define these enviroment variables somewhere in the code (nuxt.config.js ?)
Solution
Please see the accepted answer
In addition, install nuxtjs/dotenv
npm install #nuxtjs/dotenv
and make your nuxt.config.js look like:
// nuxt.config.js
require('dotenv').config()
module.exports = {
modules: [
'#nuxtjs/dotenv',
'#nuxtjs/axios',
],
axios: {
baseURL: process.env.BASE_URL
},
}
note that require('dotenv').config() must be at the top
Theres a nuxt axios module you can use. You can declare it in the module sectiont of your nuxt.config.js so you dont need your file axios.js. This is described here https://github.com/nuxt-community/axios-module#usage
By loading it in the modules in the nuxt.config.js file you will have your axios instance accesible with this.$axios in your components.
You can declare the base url in the nuxt.config.js
modules: [
// Doc: https://github.com/nuxt-community/axios-module#usage
['#nuxtjs/axios', {
baseURL: 'http://jsonplaceholder.typicode.com'
}]
],
/*
** Axios module configuration
*/
axios: {
// See https://github.com/nuxt-community/axios-module#options
},
For "other environement variables" you can use the vuex store to have them available to all components.