How to configure react typescript project having folder paths accessible like '#components/' - node.js

I want to change the relative url imports for react-typescript project. Basically from this crap ../../../contexts/AuthContext to just clean #contexts/AuthContexts.
I have tried the following with tsconfig.json :
"compilerOptions": {
"paths": {
"#components/*": ["src/components/*"],
"#contexts/*": ["src/contexts/*"]
}
}
But I am still getting error like #contexts/AuthContexts not found. And yes I can confirm that there is a file called AuthContext in that location with exports as AuthProvider.
I have created this app with npm create vite#latest using typescript as a template.
Any help will be highly appreciated.

You need to set resolve.alias in vite.config.ts file
import { defineConfig } from "vite";
import react from "#vitejs/plugin-react";
import path from "path";
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
"#components": path.resolve(__dirname, "src/components"),
},
},
});

Related

Jest is unable to import default export from index file of absolute path: "ENOENT: no such file or directory"

I set up absolute path in my node.js typescript project.
Here's the content of my Jest config file (jest.config.js):
const { pathsToModuleNameMapper } = require('ts-jest');
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
transform: {
'^.+\\.ts?$': 'ts-jest',
},
transformIgnorePatterns: ['<rootDir>/node_modules/'],
modulePaths: ['./src'],
moduleNameMapper: pathsToModuleNameMapper({
'#/*': ['*'],
}),
clearMocks: true,
};
The above config enables Jest to understand absolute path in my code.
Below is a sample of my project structure. I have a events directory that has an index.ts file like so:
src
└─ events
└─ index.ts
When I import the default export like so:
import events from '#/events'
and run Jest it throws: "ENOENT: no such file or directory, open 'events'"
but it works if I import the default export like so
import events from '#/events/index'
How do I get Jest to recognize the index.ts file in the absolute path without explicitly specifying it?
Jest should be able to detect and use the index file of the absolute path when I import like so:
import events from '#/events'
Try to add this in your tsconfig.json
{
"compilerOptions": {
"baseUrl": "./"
},
}

Bundle NPM Package so it has different import paths with Vite and Typescript

How can I bundle my NPM package in a way that I can have different import paths for different parts of the package? I have found webpack approaches, but I am using Vite and TS.
My package looks like this:
- src
- atoms
- molecules
- organism
- index.ts (currently simply imports and exports everything)
Now I can use this currently like this
import { Button } from '#mypackage/library'
How can I do it, so I get this outcome:
import { Button } from '#mypackage/library/atom'
Here is the relevant part of my package.json
{
"entry": "src/index.ts",
"main": "dist/index.cjs.js",
"module": "dist/index.es.js",
"types": "dist/index.d.ts",
"files": [
"dist",
"src"
],
"exports": {
".": {
"import": "./dist/index.es.js",
"require": "./dist/index.cjs.js",
"types": "./dist/index.d.ts"
},
"./package.json": "./package.json",
"./atoms": "./src/atoms/index.ts",
"./molecules": "./src/molecules/index.ts",
"./organisms": "./src/organisms/index.ts",
"./theme": "./src/theme/index.ts"
},
}
Here is my vite.config.ts
export default defineConfig({
build: {
lib: {
entry: path.resolve(__dirname, 'src/index.ts'),
formats: ['es', 'cjs'],
name: '#workdigtital/component-library-react',
fileName: (format) => `index.${format}.js`
},
rollupOptions: {
external: ['react', 'react-dom'],
output: {
globals: {
react: 'React',
'react-dom': 'ReactDOM'
},
exports: 'named'
}
}
},
plugins: [react(), dts({ insertTypesEntry: true })],
resolve: {
alias: {
'#': path.resolve(__dirname, './src')
}
}
});
If I currently try an import like this, inside another project (Laravel+React), in which installed the library.
import { ThemeProvider } from '#workdigital/component-library-react/theme';
I get the following run time error (But no Typescript errors, even IntelliSense is working):
Failed to load url /resources/js/theme/ThemeProvider (resolved id: /resources/js/theme/ThemeProvider). Does the file exist?
My resulting Dist folder looks like this:
You can't have TypeScript exports, this simply won't work. An npm package should have only JS exports.
If you want to be able to selectively import different parts of your package, you must transpile them to different files.
rollup can do it, but it is lots of work, as you will have to set up a separate target for each exported file. Normally you use rollup to create a single bundle, this what this tool is made for.
tsc with a tsconfig.json will be a much better choice in your case. It does this by default, you only need to specify the output directory and it will produce a separate file for each source.
There is an excellent guide on the TypeScript site about packaging TypeScript libraries, you should probably start there.

Vite: Including files in build output

This is a Vue 3 + Vuetify + TS + Vite + VSCode project.
I'm trying to bundle an XML file in the production build. Some transformation needs to be applied on the file before spitting it out. Found this Vite plug-in that can do transformations. But unfortunately, it doesn't seem to touch XML files in any way. If I put my XML file in public folder, it gets copied to the build output, but is not processed by the transformation plugin. If I put it in assets or somewhere else under src, it is simply ignored.
How can I ask Vite to include certain file(s) in the build output and pass it through transformation?
Note: Before I migrated the project to Vite, I was using Vue 2 and WebPack, where I could use the well-known CopyWebpackPlugin to perform this transformation. Haven't been able to find locate its Vite equivalent till now.
You may want to just write a script to do the transformation and add it to your npm scripts. I created a simple chrome extension to play around with VITE. Having multiple html files was pretty simple:
import { defineConfig, BuildOptions } from 'vite'
import vue from '#vitejs/plugin-vue'
const { resolve } = require('path')
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
popup: resolve(__dirname, 'popup/index.html'),
options: resolve(__dirname, 'options/index.html'),
},
}
}
})
But I had to create a separate vite config file to process the background script since it had special configuration (didn't want hashing so I could specify the name in my manifest, esm module format), and it takes the typescript and outputs 'background.js' in the public folder:
import { defineConfig } from 'vite'
const { resolve } = require('path')
// https://vitejs.dev/config/
export default defineConfig({
build: {
emptyOutDir: false,
rollupOptions: {
input: resolve(__dirname, 'background.ts'),
output: {
format: "esm",
file: "public/background.js",
dir: null,
}
}
}
})
You could simply have the xml file in your src folder and run a special script (create a 'scripts' folder maybe) to do the transform and store the result in the public folder where vite will pick it up and copy it to the dist folder. Your 'build' script in package.json could look something like this:
"scripts": {
"build": "node scripts/transform-xml.mjs && vite build",
},
Author of the package has introduced a new option named replaceFiles in the version 2.0.1 using which you can specify the files that will be passed through the transform pipeline. I can now do the following in my vite.config.js to replace variables in my output manifest.xml file after build:
const replaceFiles = [resolve(join(__dirname, '/dist/manifest.xml'))];
return defineConfig({
...
plugins: [
vue(),
transformPlugin({
replaceFiles,
replace: {
VERSION_NUMBER: process.env.VITE_APP_VERSION,
SERVER_URL: process.env.VITE_SERVER_URL,
},
...
}),
...
});

React: Absolute Paths from Root Folder using ViteJS with TypeScript

So, in React, using vite, I'm trying to do the following structure, but seems I can't get it to work because I'm missing a concept or something, so the structure is as follows:
src/utils
src/routes
src/index.tsx
src/main.tsx
And on the index.tsx, I want to import utils and routes, and then call them at any root level as following: import {Routes, Utils} from "#", but the way I did is not working.
Meanwhile, this is how I configured it with vite:
resolve: {
alias: {
"#": path.resolve(__dirname, "src"),
},
},
Make sure index.tsx exports everything from src/utils and src/routes:
// src/index.tsx
export * from './routes'
export * from './utils'
And configure TypeScript with a path alias for #:
// tsconfig.json
{
"compilerOptions": {
"paths": {
"#": ["./src"], // 👈 needed for barrel imports from '#'
"#/*": ["./src/*"]
}
}
}
demo

How to use vuetify in nuxt js as plugin?

I need to use vuetify in my nuxt js project as plugin. I've tried package #nuxtjs/vuetify but get error
Cannot assign to read only property 'base' of object '#'
I've install my nuxt project from official codesandbox online playground in local server and on shared hosting. All the time I got the same error. I tried install node modules using npm and yarn. How I can add fresh vuetify version to last version of nuxt js as plugin with npm package vuetify?
Install vuetify and #mdi/font
Create a file vuetify.js in your plugins folder with the following code:
import Vue from 'vue'
import Vuetify from 'vuetify'
import colors from './../config/colors'
import 'vuetify/dist/vuetify.min.css'
import '#mdi/font/css/materialdesignicons.css'
Vue.use(Vuetify)
export default ctx => {
const vuetify = new Vuetify({
theme: {
themes: {
light: {
...colors
},
dark: {
// colors
}
}
}
})
ctx.app.vuetify = vuetify
ctx.$vuetify = vuetify.framework
}
Edit nuxt.config.js file by adding vuetify to plugins like this
{
...
plugins: ['~plugins/vuetify.js'],
...
}
I achieved this with the following:
npm install --save vuetify
create a file vuetify.js in your plugins folder with the following code:
import Vue from 'vue'
import Vuetify from 'vuetify'
Vue.use(Vuetify)
Amend your nuxt.config.js:
plugins: ['~plugins/vuetify.js'],
build: {
vendor: ['vuetify']
}
There is a discussion of this issue here: https://github.com/nuxt-community/vuetify-module/issues/268
Fixing custom colours and specifying options in external files seem to affect this.
If you have colours specified in the options, replace primary: colors.blue with primary: colors.blue.base.
I have / had same issue. I simply made sure to use version 1.10.3 or below defined explicitly in package.json
"#nuxtjs/vuetify": "1.10.3", (not with the ^1.10.3)
I also noticed any version over this also adds an "undefined" 404 to the end of every url request. I posted on Nuxt / CMTY but they have a user base of zero people who answer any questions.
Choose Vuetify as ur UI Framework when initial a Nuxt project
Create a new file in plugins/vuetify.js
import Vue from 'vue'
import Vuetify from 'vuetify'
import colors from 'vuetify/es5/util/colors'
Vue.use(Vuetify)
export default new Vuetify({
theme: {
light: true,
themes: {
light: {
primary: colors.blue.darken2,
accent: colors.grey.darken3,
secondary: colors.amber.darken3,
info: colors.teal.lighten1,
warning: colors.amber.base,
error: colors.deepOrange.accent4,
success: colors.green.accent3
}
}
}
})
Add the plugin config inside nuxt.config.js
export default {
plugins: ['~/plugins/vuetify.js'],
}
Restart server, npm run dev
An image example:
vuetify.js
Done!
you can do the following steps in order and finally use Vuetify components:
1- Setup vuetify
yarn add vuetify#next sass
2- Your package.json should now look similar to the following:
// package.json
"devDependencies": {
"nuxt": "3.0.0-rc.1"
},
"dependencies": {
"sass": "^1.51.0",
"vuetify": "^3.0.0-beta.1"
}
3- Creating your Vuetify plugin
You must create this file in the plugin folder and put these codes inside it.
// plugins/vuetify.js
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
export default defineNuxtPlugin(nuxtApp => {
const vuetify = createVuetify({
components,
directives,
})
nuxtApp.vueApp.use(vuetify)
})
4- Configure Nuxt 2 or 3 to use our new plugin
In this section, you should put these codes in the nuxt.config.ts file like this
// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'
// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
css: ['vuetify/lib/styles/main.sass'],
build: {
transpile: ['vuetify'],
},
vite: {
define: {
'process.env.DEBUG': false,
},
},
})
5- Finally, in order to test that you have done the steps correctly, you can use this component in your code to see if Vuetify is installed correctly or not.
<v-btn>Button</v-btn>
Tip: If you have done these steps or you want to use a new component, in many cases it is better to stop and restart your project once.

Resources