vue-test-utils - Memory Leak with shallowMount / mount - vuejs2

Subject of the issue
Seeing a 2MB heap size increase after each test using shallowMount / mount.
Steps to reproduce
Run this command with the below setup:
./node_modules/.bin/jest -- "DummyTest-test.js"
Vue Version 2.7.10
Vue Test Utils Version 1.3.3
Jest Version 29.0.3
Node Version 14.20.0
vue/vue2-jest Version 28.1.0
DummyTest-test.js
import { shallowMount } from "#vue/test-utils";
import DummyComponent from "../DummyComponent.vue";
let iterations = [...Array(9999).keys()];
let wrapper;
let heap;
afterAll(() => {
iterations = null;
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
heap = null;
});
it.each(iterations)(`Test`, () => {
wrapper = shallowMount(DummyComponent);
heap = (process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2);
console.log(`Heap Size: ${heap} MB`);
expect(true).toBe(true);
});
DummyComponent.vue
<template>
<div>
<p>Hi</p>
</div>
</template>
<script>
export default {
name: "DummyComponent",
};
</script>
jest.config.js
module.exports = {
testEnvironment: "jsdom",
transform: {
"^.+\\.js$": "babel-jest",
"^.+\\.vue$": "#vue/vue2-jest",
},
};
Expected behavior
Heap Size should remain consistent after each iteration of the test.
Actual behavior
Seeing a 2MB memory leak.
0.2MB of the leak looks to be coming from the usage of console.log, but the rest of the leak is coming from the mounting step.
Attempted Solutions
I have posted this same question on the GitHub Issues page.
Changing node versions (12, 16, 18) did not resolve the issue.
This is a Vue 2 project, so I cannot use vue-test-utils v2. However, I did a brief test on Vue 3 with Vue Test Utils v2, and it looked the issue was still present.
Looking for help on what to try next, or if others are experiencing the same issue.
I did see this StackOverflow post from 4 years ago, but I am using wrapper.destroy() and wrapper = null after each test and the issue is still present.
To prevent CI from grinding to a halt, I'm using the workerIdleMemoryLimit option from the latest version of Jest as a band-aid.

Related

Unable to load stencil components lib with Vue3 using Vite

I created a sample project to reproduce this issue: https://github.com/splanard/vue3-vite-web-components
I initialized a vue3 project using npm init vue#latest, as recommanded in the official documentation.
Then I installed Scale, a stencil-built web components library. (I have the exact same issue with the internal design system of my company, so I searched for public stencil-built libraries to reproduce the issue.)
I configured the following in main.ts:
import '#telekom/scale-components-neutral/dist/scale-components/scale-components.css';
import { applyPolyfills, defineCustomElements } from '#telekom/scale-components-neutral/loader';
const app = createApp(App);
app.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('scale-')
applyPolyfills().then(() => {
defineCustomElements(window);
});
And the same isCustomElement function in vite.config.js:
export default defineConfig({
plugins: [vue({
template: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('scale-')
}
}
})]
// ...
})
I inserted a simple button in my view (TestView.vue), then run npm run dev.
When opening my test page (/test) containing the web component, I have an error in my web browser's console:
failed to load module "http://localhost:3000/node_modules/.vite/deps/scale-button_14.entry.js?import" because of disallowed MIME type " "
As it's the case with both Scale and my company's design system, I'm pretty sure it's reproducible with any stencil-based components library.
Edit
It appears that node_modules/.vite is the directory where Vite's dependency pre-bundling feature caches things. And the script scale-button_14.entry.js the browser fails to load doesn't exist at all in node_modules/.vite/deps. So the issue might be linked to this "dependency pre-bundling" feature: somehow, could it not detect the components from the library loader?
Edit 2
I just found out there is an issue in Stencil repository mentioning that dynamic imports do not work with modern built tools like Vite. This issue has been closed 7 days ago (lucky me!), and version 2.16.0 of Stencil is supposed to fix this. We shall see.
For the time being, dropping the lazy loading and loading all the components at once through a plain old script tag in the HTML template seems to be an acceptable workaround.
<link rel="stylesheet" href="node_modules/#telekom/scale-components/dist/scale-components/scale-components.css">
<script type="module" src="node_modules/#telekom/scale-components/dist/scale-components/scale-components.esm.js"></script>
However, I can't get vite pre-bundling feature to ignore these imports. I configured optimizeDeps.exclude in vite.config.js but I still get massive warnings from vite when I run npm run dev:
export default defineConfig({
optimizeDeps: {
exclude: [
// I tried pretty much everything here: no way to force vite pre-bundling to ignore it...
'scale-components-neutral'
'#telekom/scale-components-neutral'
'#telekom/scale-components-neutral/**/*'
'#telekom/scale-components-neutral/**/*.js'
'node_modules/#telekom/scale-components-neutral/**/*.js'
],
},
// ...
});
This issue has been fixed by Stencil in version 2.16.
Upgrading Stencil to 2.16.1 in the components library dependency and rebuilding it with the experimentalImportInjection flag solved the problem.
Then, I can import it following the official documentation:
main.ts
import '#telekom/scale-components-neutral/dist/scale-components/scale-components.css';
import { applyPolyfills, defineCustomElements } from '#telekom/scale-components-neutral/loader';
const app = createApp(App);
applyPolyfills().then(() => {
defineCustomElements(window);
});
And configure the custom elements in vite config:
vite.config.js
export default defineConfig({
plugins: [vue({
template: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('scale-')
}
}
})]
// ...
})
I did not configure main.ts
stencil.js version is 2.12.1,tsconfig.json add new config option in stencil:
{
"compilerOptions": {
...
"skipLibCheck": true,
...
}
}
add new config option in webpack.config.js :
vue 3 document
...
module: {
rules:[
...
{
test: /\.vue$/,
use: {
loader: "vue-loader",
options: {
compilerOptions: {
isCustomElement: tag => tag.includes("-")
}
}
}
}
...
]
}
...

Trying to get Vue-heatmapjs working on a nuxt application

Hello first time posting on stack overflow so sorry
I am trying to get vue-heatmapjs https://github.com/BrockReece/vue-heatmapjs to work in my nuxt js project. Since i don't have a main.js I've put it in a plugin and I don't recieve any errors. the scroll map for this project seems to work however its simply the click map.
plugins: [
{ ssr: false, src: "~plugins/heatmap-plugin.js"}
],
import vue from 'vue'
import { Subject } from 'rxjs';
import Vueheatmap from 'vue-heatmapjs'
const stream = new Subject();
export const pauser = new Subject();
vue.config.productionTip = false;
vue.use(Vueheatmap, {
stream,
pauser,
heatmapPreload: [{ x: 50, y: 50, value: 100 }],
afterAdd(data) {
console.log(data)
// you can fire this back to your analytics server
},
});
stream.subscribe(console.log);
Above is my plugin code
So After alot of searching its because the Dependancies for this heatmap app weren't compatible with our current nuxt and vue setup so I had set it all up again and change the dependancies and rewrite alot of the code.
Vue-rx is one of the keys i had to install aswell as update rxjs

Web3js fails to import in Vue3 composition api project

I've created a brand new project with npm init vite bar -- --template vue. I've done an npm install web3 and I can see my package-lock.json includes this package. My node_modules directory also includes the web3 modules.
So then I added this line to main.js:
import { createApp } from 'vue'
import App from './App.vue'
import Web3 from 'web3' <-- This line
createApp(App).mount('#app')
And I get the following error:
I don't understand what is going on here. I'm fairly new to using npm so I'm not super sure what to Google. The errors are coming from node_modules/web3/lib/index.js, node_modules/web3-core/lib/index.js, node_modules/web3-core-requestmanager/lib/index.js, and finally node_modules/util/util.js. I suspect it has to do with one of these:
I'm using Vue 3
I'm using Vue 3 Composition API
I'm using Vue 3 Composition API SFC <script setup> tag (but I imported it in main.js so I don't think it is this one)
web3js is in Typescript and my Vue3 project is not configured for Typescript
But as I am fairly new to JavaScript and Vue and Web3 I am not sure how to focus my Googling on this error. My background is Python, Go, Terraform. Basically the back end of the back end. Front end JavaScript is new to me.
How do I go about resolving this issue?
Option 1: Polyfill Node globals/modules
Polyfilling the Node globals and modules enables the web3 import to run in the browser:
Install the ESBuild plugins that polyfill Node globals/modules:
npm i -D #esbuild-plugins/node-globals-polyfill
npm i -D #esbuild-plugins/node-modules-polyfill
Configure optimizeDeps.esbuildOptions to use these ESBuild plugins.
Configure define to replace global with globalThis (the browser equivalent).
import { defineConfig } from 'vite'
import GlobalsPolyfills from '#esbuild-plugins/node-globals-polyfill'
import NodeModulesPolyfills from '#esbuild-plugins/node-modules-polyfill'
export default defineConfig({
⋮
optimizeDeps: {
esbuildOptions: {
2️⃣
plugins: [
NodeModulesPolyfills(),
GlobalsPolyfills({
process: true,
buffer: true,
}),
],
3️⃣
define: {
global: 'globalThis',
},
},
},
})
demo 1
Note: The polyfills add considerable size to the build output.
Option 2: Use pre-bundled script
web3 distributes a bundled script at web3/dist/web3.min.js, which can run in the browser without any configuration (listed as "pure js"). You could configure a resolve.alias to pull in that file:
import { defineConfig } from 'vite'
export default defineConfig({
⋮
resolve: {
alias: {
web3: 'web3/dist/web3.min.js',
},
// or
alias: [
{
find: 'web3',
replacement: 'web3/dist/web3.min.js',
},
],
},
})
demo 2
Note: This option produces 469.4 KiB smaller output than Option 1.
You can avoid the Uncaught ReferenceError: process is not defined error by adding this in your vite config
export default defineConfig({
// ...
define: {
'process.env': process.env
}
})
I found the best solution.
The problem is because you lose window.process variable, and process exists only on node, not the browser.
So you should inject it to browser when the app loads.
Add this line to your app:
window.process = {
...window.process,
};

error PropType not found in 'vue' in open source project

i am trying to work on an opensource software for NLP named doccano,i tried running only the frontend part where i ran the command npm install to get all needed dependencies then when i run npm run dev it starts compiling and then fails with this error
/home/nissow/Documents/doccano/doccano/frontend/components/project/FormDelete.vue
33:14 error PropType not found in 'vue' import/named
and when i checked the FormDelete.vue i did not notice any errors and no errors were detected on vscode either
<script lang="ts">
import Vue,{ PropType } from 'vue'
import BaseCard from '#/components/utils/BaseCard.vue'
import { ProjectDTO } from '~/services/application/project/projectData'
export default Vue.extend({
components: {
BaseCard
},
props: {
selected: {
type: Array as PropType<ProjectDTO[]>,
default: () => []
}
},
computed: {
nonDeletableProjects(): ProjectDTO[] {
return this.selected.filter(item => !item.current_users_role.is_project_admin)
},
hasNonDeletableProjects(): boolean {
return this.nonDeletableProjects.length > 0
}
}
})
</script>
here's package.json content :
and here's the second part
import type { PropType } from 'vue'
see detail https://github.com/nuxt-community/composition-api/issues/189
It was also a problem elsewhere.
Sounds like a known bug in eslint and typescript. It doesn't seem to cause an error depending on the version.
https://github.com/nuxt-community/composition-api/issues/189
i just made it work, by installing yarn and then running, yarn dev as it was suggested in the README.MD the first time i was doing it with npm run dev.

getting error when trying to upgrade to vuetify 2.0

Ok so I am trying for the second time to migrate thus far it has been a complete failure it seems that vuetify is not detected, unfortunately I cannot share my full repo since it is work related, but will describe steps and share relevant code.
Project was created with vue-cli 3.3.0 with a vue.config.js file for environment variables.
1) npm uninstall vuetify
2)vue add vuetify
3)npm run serve
my site does not load and I get this error (adding code):
//vue.config.js
module.exports = {
chainWebpack: (config) => {
config.plugin('define')
.tap(([options, ...args]) => {
let env = options['process.env'].VUE_APP_ENV.replace(/"/g,'');
let envMdl = require('./build/' + env.toString() + '.js');
// replace all current by VUE concrente ones to be passed to the app
const processEnv = Object.assign({}, options['process.env'])
Object.keys(envMdl).forEach(function (k) {
processEnv['VUE_APP_' + k] = envMdl[k];
});
const ret = Object.assign({}, options, {'process.env': processEnv});
return [
ret,
...args
]
})
}
}
//vuetify.js
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
Vue.use(Vuetify)
export default new Vuetify({
icons: {
iconfont: 'mdiSvg',
},
})
//main.js
import vuetify from './plugins/vuetify'
...
new Vue({
vuetify,
router,
store,
i18n,
render: h => h(App),
...
Error message (and screenshot): Uncaught TypeError: _lib.default is not a constructor
at eval (vuetify.js?402c:6)
The main problem is that Vuetify v1 works under the Stylus preprocessor, and in v2 it works under the SASS preprocessor, and I personally do not recommend migrating to v2 if it is too advanced and even worse if it has custom Vuetify components.