How to setup aliased paths? - vuejs2

I'm using vue-cli 2.8.1.
Project initiated with vue init webpack project.
How to specify an alias and use it to resolve paths?
For instance, this is how it's done in webpack:
alias: {
components: path.resolve(__dirname, 'src/components/')
}
Then it's possible to make imports like this:
import Component from 'components/component'; // note there's no './' in the path

Related

How to import index.vue files without specifying the file name using vue 3 and vite?

I started working recently on a Vue 3 application which runs with vite and I am trying to restructure the directories so that I can group components and related sub-components in folders.
I am currently using /path/to/MyComponent/index.vue to import the higher-hierarchy component, and I would like to write the import statement without specifying the file name, so that I could do something like this:
import MyComponent from `#/path/to/MyComponent`
where the files structure looks like the following:
path
│
└───to
│
└───MyComponent
│ index.vue
│ SubComponent.vue
│ ...
I tried to play with the resolve.alias property in the vite.config.ts file, but I wasn't successful. Anyone managed to achieve this?
This is one of the attempts:
export default defineConfig({
...
resolve: {
alias: [
{
find: "#",
replacement: fileURLToPath(new URL("./src", import.meta.url)),
},
{
find: /(^(?!.*[.](ts|js|tsx|jsx|vue|)$))/,
replacement: "$1/index.vue",
},
],
},
...
After trying various things I found a solution in line with my original post involvin modifying the vite.config.ts file resolve.alias property.
In addition I had to modify the tsconfig.json file to make sure that typescript compiler is also able to resolve the path to the index.vue file.
This is how I achieved importing a index.vue component only referencing the parent folder name:
1. Vite configuration
// vite.config.ts
export default defineConfig({
resolve: {
alias: [
{
find: /#\/components\/((?!.*[.](ts|js|tsx|jsx|vue)$).*$)/,
replacement: fileURLToPath(
new URL("./src/components/$1/index.vue", import.meta.url)
),
},
{
find: "#",
replacement: fileURLToPath(new URL("./src", import.meta.url)),
},
// ...
The above configuration code will tell vite to check if the import statement contains with #/components and does NOT end with any of the following extensions: ts|js|tsx|jsx|vue. E.g. #/components/MyComponent.
When these criteria are met the find path will be replaced with the path to the index.vue file within the src/components folder. E.g. #/components/MyComponent/index.vue.
The only limitations of the above solution is that it targets a specific folder (in this case the components folder). However we can add more alias objects to match any other folder where we want to implement this import pattern.
2. Typescript configuration
If using typescript ESLint will throws two errors: Missing file extension and Unable to resolve path to module. This because the typescript compiler is agnostic of the above vite configuration.
For this reason I also had to modify the tsconfig.json file as following:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"#/components/*": ["./src/components/*", "./src/components/*/index.vue"],
"#/*": ["./src/*"]
}
}
The above code will leverage Typescript module resolution path mapping to map everything that matches #/components/* to ./src/components/*, where * represents the path within the ./src/components. This path is relative to where the tsconfig.json file reside (as defined by the baseUrl parameter).
If a component is not found, Typescript compiler will look inside ./src/components/*/index.vue.

Loader is required to be configured to import images using Vite?

I have a vue project which uses Vite in place of Webpack, and when I try to use import x from './src/assets/my/path/to/image.png' to resolve an image to compile-time URL, I am greeted by the following error message:
✘ [ERROR] No loader is configured for ".png" files: src/assets/my/path/to/image.png
The entire project is pretty close to the scaffold project given by npm init vue#latest (using vue3) so my vite.config.js is pretty basic:
export default defineConfig({
plugins: [vue(), VitePWA({})],
resolve: {
alias: {
"#": fileURLToPath(new URL("./src", import.meta.url)),
},
},
build: {
manifest: true,
polyfillModulePreload: true,
}
});
What am I missing? How can I configure this? I can't find anything in Vite documentation about loaders.
I had a quite similar issue with my project that I couldn't really solve. The issue seemed that only initially loaded png files were added. Because I am new to Vite, my efforts with the vite.config.js were fruitless.
Instead, I found a different solution to import the assets (import img from '/path/to/img.png' ) in respective js files directly instead of vite.config.js. Since I used these assets for replacement images for toggling buttons, it was a quick fix. Maybe it helps you, too.

How to create a library with dynamic imports which can be imported by Nuxt?

I am trying to reuse Nuxt.js components from one project in another project. So I created a new project which imports the components needed and then exports them as a npm package.
npm package (main.js)
import SomeComponent from '../foobar/SomeComponent.vue'
export default {
install (Vue) {
Vue.component(SomeComponent)
}
}
export {
SomeComponent
}
npm package (webpack.config.js)
module.exports = {
entry: path.resolve(__dirname + '/src/main.js'),
output: {
path: path.resolve(__dirname + '/dist/'),
chunkFilename: '[name].build.js',
filename: 'build.js',
libraryTarget: 'umd',
libraryExport: 'default',
library: 'MyLibrary',
umdNamedDefine: true
}
}
Then in my new Nuxt.js project I can simply import the npm package and the components will be installed automatically. While this works fine when not using any code splitting it will throw an error when trying to use dynamic imports in the SomeComponent.vue file.
When adding dynamic imports in my component like so import(/* webpackChunkName: "mapbox" */ 'mapbox-gl') the chunks will be created but when running Nuxt in development mode I always get the error:
Uncaught (in promise) ChunkLoadError: Loading chunk 1 failed.
Nuxt does not find the created chunk files. I tried playing around with publicPath but I don't get what path would be the right one for Nuxt to be able to access them?

How to force .vue extension in all imports using eslint?

In VS Code with Vetur (the extension for working with Vue), "Go to definition" will not work on component imports where there's no .vue extension at the end (Vetur FAQ link)
I was wondering if there's an eslint rule that will force the user to always provide an extension when using an import statement in .vue files?
Examples:
✔️ This works:
import HelloWorld from '#/components/HelloWorld.vue'
Right clicking on HelloWorld and pressing Go to definition in VS Code wil take you to the HelloWorld.vue file.
❌ This doesn't:
import HelloWorld from '#/components/HelloWorld'
If you press Go to definition on HelloWorld (leftmost), VS Code will just move the cursor to the HelloWorld you just right clicked. Intended behavior is that we move to the HelloWorld.vue file.
It's easy to do this for paths like ./src/components/A.vue. It's trickier for #/components/A.vue because you need to resolve the # alias.
The below solution works for both.
To force .vue extensions in paths, do this:
1. Install eslint-plugin-import, which extends functionality of eslint by linting import paths. Also install with a custom path resolver - eslint-import-resolver-alias for it:
npm install eslint-plugin-import eslint-import-resolver-alias --save-dev
2. Then, in your ESLint config file (.eslintrc.js, or eslintConfig field in package.json etc), add this:
// I'm using .eslintrc.js
module.exports = {
//...unimportant properties like root, env, extends, parserOptions etc
plugins: ["import"],
settings: {
"import/resolver": {
alias: {
map: [
["#", "./src"], //default # -> ./src alias in Vue, it exists even if vue.config.js is not present
/*
*... add your own webpack aliases if you have them in vue.config.js/other webpack config file
* if you forget to add them, eslint-plugin-import will not throw linting error in .vue imports that contain the webpack alias you forgot to add
*/
],
extensions: [".vue", ".json", ".js"]
}
}
}
}
Here's a repository with a working demo that implements forcing .vue path in imports correctly.
And a screenshot from VSCode and output from npm run lint:
You need to configure eslint-plugin-import to set force on vue files, just add this rule in eslint config
"import/extensions": ["error", "ignorePackages", { "vue": "always" }],

Stencil and Sass file

I am trying to port a React component to Stencil.
The component .scss file has an #import for another A.scss file. That A.scss file #import the bootstrap-sass/assets/stylesheet/bootstrap/_variables and #import another B.scss file.
Can Stencil handle that or do I need to merge everything in one file?
You can import other Sass files; you don't need to merge everything to one single file.
You can keep using Sass as you are using it with React. Just keep in mind that to be able to use Sass with Stencil, you have to install the Sass plugin and add the plugin to the plugins array in your stencil.config.js file.
For more information, check the Sass documentation on the Stencil website.
In your stencil.config.ts (or stencil.config.js) file:
export const config: Config = {
plugins: [
sass({
includePaths: [path.resolve(__dirname, 'path/to/styles')]
})
]
};
Yes, it can handle Sass files and their imports.
Install package stencil/sass:
npm i #stencil/sass -D
In your stencil.config.ts file:
import { Config } from "#stencil/core";
import { sass } from "#stencil/sass";
export const config: Config = {
// ... You configuration
plugins: [
sass({
includePaths: ["./node_modules/"],
}),
],
};
In the above example, we're telling the Stencil compiler to compile Sass files. The includePaths array tells the compiler the directories/files it should look into for the Sass files.
In order to use #import from a Node.js package, all you need is:
#import "~bootstrap-sass/assets/stylesheet/bootstrap/_variables";
Note: The ~ operator here is necessary when not importing using relative paths(./style.scss, ../../style.scss, etc.)
If you are importing the b.scss file using relative paths (./b.scss, ../b.scss, etc.), you won't need to add anything else to Sass plugin configuration.
I never tried multiple imports, but I can't see why this wouldn't work.
To get Stencil working with .scss, you should install this plugin, as described here.
npm install #stencil/sass --save-dev
Then add this property to config in file stencil.config.ts.
plugins: [
sass()
]