Topic: MDBVue - Better Typescript Support
jammerxd2 priority asked 8 months ago
Expected behavior
Components are not dependent on index.free.ts or index.pro.ts
Additionally, components should not be traversing all the way to the src
folder to make imports.
Example:
src/components/free/forms/MDBInput.vue:
import vMdbClickOutside from "../../../../src/directives/free/mdbClickOutside";
can be changed to
import vMdbClickOutside from "../../../directives/free/mdbClickOutside";
Pro Example:
src/copmonents/pro/navigation/MDBSideNav.vue:
import MDBScrollbar from "../../../../src/components/pro/methods/MDBScrollbar.vue";
can be changed to
import MDBScrollbar from "../methods/MDBScrollbar.vue";
Actual behavior
A few components make imports from the index.free.ts or index.pro.ts files - which in turn causes a circular dependency which then causes issues when trying to run a type check in typescript (using vue-tsc for example).
Additionally, many components traverse the relative directory tree all the way up to the src
folder, necessitating another nested src
folder inside of the kit.
Fixes
The following files require the imports relying on index.free or index.pro to be changed to be relative references otherwise the index.free.ts and index.pro.ts files create a circular dependency when compiling the typescript.
src/components/free/components/MDBDropdownMenu.vue
Line 56: import { MDBInput } from "../../../index.free";
to import MDBInput from "../forms/MDBInput.vue";
src/components/free/navigation/MDBNavbarToggler.vue
Line 23: import { MDBIcon } from "../../../index.free";
to import MDBIcon from "../content-styles/MDBIcon.vue";
src/components/pro/components/forms/MDBTimepickerFooter.vue
Line 49: import { mdbRipple as vMdbRipple } from "../../../../index.free";
to import vMdbRipple from "../../../../directives/free/mdbRipple"
src/components/pro/components/forms/MDBTimepicker/MDBTimepickerHeader.vue
Line 180: import { mdbRipple as vMdbRipple } from "../../../../index.free";
to import vMdbRipple from "../../../../directives/free/mdbRipple"
src/components/pro/navigation/MDBSideNavMenu.vue
Line 43: import { MDBInput } from "../../../index.free";
to import MDBInput from "../../free/forms/MDBInput.vue";
Use MDB in a vuejs project
If you're new to typescript, chances are your app was created with vite or create-app and has typescript enabled. By default, typescript uses 'strict' typechecking, which is more stringent and enforces stronger requirements for developers. The MDB library (at least vuejs version) has very poor support for typescript and requires the following flags be turned OFF via tsconfig.json
:
"strict": false,
"noUnusedLocals": false,
"noUnusedParameters": false,
The issue I ran into is I didn't want to set these flags in my main app, only for the MDB vuejs library. Furthermore, doing this allows me to reduce the size of my built application, and allows the vite builder to split the js files up better - basing off of the individual imports, rather than always importing all and using the 550kb main file.
To setup a nested tsconfig.json project structure, we will need to make a project structure that looks like:
| tsconfig.json
| src
| tsconfig.json
| mdb5-vue-ui-kit
| tsconfig.json
Start by creating a blank vuejs app - npm create vite@latest
- and enable typescript.
Create a new folder in the src
folder - mdb5-vue-ui-kit
(or mdb5-vue-ui-kit-pro-advanced
or whatever tier of the kit you have).
Copy only the src
folder into the folder just created in the app - you should have src/mdb5-vui-ui-kit/src
(yes it's intentionally nested into the src
folder again)
Placing the ui kit source files inside the src
folder of the app is required to avoid the typescript compiler (and vscode) from complaining about the source files not being in the rootDir
of the project.
Create a tsconfig.json file inside the src/mdb5-vue-ui-kit/src
folder:
src/mdb5-vue-ui-kit/src/tsconfig.json
:
{
"compilerOptions": {
"strict": false,
"noUnusedLocals": false,
"noUnusedParameters": false,
"noFallthroughCasesInSwitch": false,
"allowSyntheticDefaultImports": true,
"useDefineForClassFields": true,
"rootDir": ".",
"outDir": "../../../../dist/mdb5-vue-ui-kit",
"composite": true,
"target": "ES2020",
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
// Bundler mode
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
},
"include": ["./**/*.ts", "./**/*.tsx", "./**/*.vue"]
}
Create a tsconfig.json file inside the app src
folder:
src/tsconfig.json
:
{
"compilerOptions": {
"rootDir": ".",
"outDir": "../dist",
"composite": true,
"target": "ES2020",
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
// Bundler mode
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"allowSyntheticDefaultImports": true,
"useDefineForClassFields": true,
"paths": {
"@/*": ["./*"],
"@mdb/*": ["./mdb5-vue-ui-kit/src/*"]
}
},
"references": [
{ "path": "./mdb5-vue-ui-kit/src" },
{ "path": "../tsconfig.node.json" }
],
"include": ["*.ts","*.vue", "*.tsx","./**/*.ts", "./**/*.tsx", "./**/*.vue", "./mdb5-vue-ui-kit/src/**/*.ts", "./mdb5-vue-ui-kit/src/**/*.vue", "./mdb5-vue-ui-kit/src/**/*.tsx"],
}
The key note here is the references
array - the array is a list of other typescript "project" files that this tsconfig.json
is dependent on. Each referenced "project" will have it's files compiled using it's own tsconfig.json
options.
Adding the mdb5-vue-ui-kit/src
files to the include
array tells the typescript compiler to include those files as part of the project, but because of the project reference, the mdb5-vue-ui-kit\src\tsconfig.json
file will get used.
Next, update the tsconfig.json
in the project root to look like the following:
tsconfig.json
:
{
"compilerOptions": {
"rootDir": ".",
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
// Bundler mode
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"allowSyntheticDefaultImports": true,
"paths": {
"@/*":["./src/*"],
"@mdb/*": ["./src/mdb5-vue-ui-kit/src/*"]
}
},
"files": [],
"references": [
{ "path": "./src/mdb5-vue-ui-kit/src" },
{ "path": "./src" },
{ "path": "./tsconfig.node.json" }
]
}
And finally the vite.config.ts
file:
import { fileURLToPath, URL } from 'node: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)),
'@mdb':fileURLToPath(new URL('./src/mdb5-vue-ui-kit/src',import.meta.url))
}
}
})
Install Dependencies
The MDB vue ui kit has several other packages that are required to be installed, at the time of writing they are:
- @popperjs/core
- chart.js
- chartjs-plugin-datalabels
- deepmerge
- vue3-perfect-scrollbar
There are also other dev dependencies:
- sass
- @types/node
- @types/chart.js
All Done
Now instead of importing components from 'mdb-vue-ui-kit' or the index file, components can be individually imported from their respective .vue files - and without typescript compile errors when strict checking is on.
For example:
src/components/HelloWorld.vue
(as taken from the sample vue app):
<script setup lang="ts">
import MDBContainer from '../mdb5-vue-ui-kit/src/components/free/layout/MDBContainer.vue';
import MDBRow from '../mdb5-vue-ui-kit/src/components/free/layout/MDBRow.vue';
import MDBCol from '../mdb5-vue-ui-kit/src/components/free/layout/MDBCol.vue';
</script>
<template>
<MDBContainer>
<MDBRow>
<MDBCol sz="12">
<h1 class="text-center">HELLO WORLD</h1>
</MDBCol>
</MDBRow>
</MDBContainer>
</template>
Additionally, import the main scss file in src/main.ts
:
import './mdb5-vue-ui-kit/src/scss/index.pro.scss'
or import './mdb5-vue-ui-kit/src/scss/index.pro.dark.scss'
for the dark version
Thank You
If you made it this far in reading through everything, congratulations! And thank you for taking the time to read through all this.
Bartosz Cylwik staff answered 8 months ago
Hi! Thank you for that message! We are planning to update the typescript support for the next release. I'm also adding the issue with importing files to our list to check.
Best Regards!
jammerxd2 priority commented 8 months ago
So long as the functionality/project layout I mentioned above remains working :)
FREE CONSULTATION
Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.
Answered
- ForumUser: Priority
- Premium support: Yes
- Technology: MDB Vue
- MDB Version: MDB5 4.1.1
- Device: Any
- Browser: Any
- OS: Any
- Provided sample code: Yes
- Provided link: No
jammerxd2 priority commented 8 months ago
And my sources: https://stackoverflow.com/questions/68262454/angular-monorepo-error-ts6059-file-ng-youtube-api-service-ngtypecheck-ts-is-n/76500288#76500288
https://stackoverflow.com/questions/55753163/package-json-is-not-under-rootdir/61467483#61467483
This one was by far the most useful: https://stackoverflow.com/questions/60896829/monorepo-with-rootdirs-produces-unwanted-sudirectories-such-as-src-in-outdi/61513685#61513685