How to reference static assets within vue javascript - javascript

I'm looking for the right url to reference static assets, like images within Vue javascript.
For example, I'm creating a leaflet marker using a custom icon image, and I've tried several urls, but they all return a 404 (Not Found):
Main.vue:
var icon = L.icon({
iconUrl: './assets/img.png',
iconSize: [25, 25],
iconAnchor: [12, 12]
});
I've tried putting the images in the assets folder and the static folder with no luck. Do I have to tell vue to load those images somehow?

For anyone looking to refer images from template, You can refer images directly using '#'
Example:
<img src="#/assets/images/home.png"/>

In a Vue regular setup, /assets is not served.
The images become src="data:image/png;base64,iVBORw0K...YII=" strings, instead.
Using from within JavaScript: require()
To get the images from JS code, use require('../assets.myImage.png'). The path must be relative (see below).
So your code would be:
var icon = L.icon({
iconUrl: require('./assets/img.png'), // was iconUrl: './assets/img.png',
// iconUrl: require('#/assets/img.png'), // use # as alternative, depending on the path
// ...
});
Use relative path
For example, say you have the following folder structure:
- src
+- assets
- myImage.png
+- components
- MyComponent.vue
If you want to reference the image in MyComponent.vue, the path sould be ../assets/myImage.png
Here's a DEMO CODESANDBOX showing it in action.

A better solution would be
Adding some good practices and safity to #acdcjunior's answer, to use # instead of ./
In JavaScript
require("#/assets/images/user-img-placeholder.png")
In JSX Template
<img src="#/assets/images/user-img-placeholder.png"/>
using # points to the src directory.
using ~ points to the project root, which makes it easier to access the node_modules and other root level resources

In order for Webpack to return the correct asset paths, you need to use require('./relative/path/to/file.jpg'), which will get processed by file-loader and returns the resolved URL.
computed: {
iconUrl () {
return require('./assets/img.png')
// The path could be '../assets/img.png', etc., which depends on where your vue file is
}
}
See VueJS templates - Handling Static Assets

Right after oppening script tag just add import someImage from '../assets/someImage.png'
and use it for an icon url iconUrl: someImage

this finally worked for me, image passed as prop:
<img :src="require(`../../assets/${image}.svg`)">

What system are you using? Webpack? Vue-loader?
I'll only brainstorming here...
Because .png is not a JavaScript file, you will need to configure Webpack to use file-loader or url-loader to handle them. The project scaffolded with vue-cli has also configured this for you.
You can take a look at webpack.conf.js in order to see if it's well configured like
...
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
...
/assets is for files that are handles by webpack during bundling - for that, they have to be referenced somewhere in your javascript code.
Other assets can be put in /static, the content of this folder will be copied to /dist later as-is.
I recommend you to try to change:
iconUrl: './assets/img.png'
to
iconUrl: './dist/img.png'
You can read the official documentation here: https://vue-loader.vuejs.org/en/configurations/asset-url.html
Hope it helps to you!

It works for me by using require syntax like this:
$('.eventSlick').slick({
dots: true,
slidesToShow: 3,
slidesToScroll: 1,
autoplay: false,
autoplaySpeed: 2000,
arrows: true,
draggable: false,
prevArrow: '<button type="button" data-role="none" class="slick-prev"><img src="' + require("#/assets/img/icon/Arrow_Left.svg")+'"></button>',

Having a default structure of folders generated by Vue CLI such as src/assets you can place your image there and refer this from HTML as follows <img src="../src/assets/img/logo.png"> as well (works automatically without any changes on deployment too).

I'm using typescript with vue, but this is how I went about it
<template><div><img :src="MyImage" /></div></template>
<script lang="ts">
import { Vue } from 'vue-property-decorator';
export default class MyPage extends Vue {
MyImage = "../assets/images/myImage.png";
}
</script>

You could define the assets path depending on your environment
const dev = process.env.NODE_ENV != 'production';
const url = 'https://your-site.com';
const assets = dev ? '' : url;
<template>
<img :src="`${assets}/logo.png`"/>
<p>path: {{assets}}</p>
</template>
<script>
export default {
data: () => ({
assets
})
}
</script>
Ideally this would be inside an utils js file, or as an extended app defineProperty, like:
const app = createApp(component);
app.config.globalProperties.$assets = assets;
app.mount(element);
and will be available as:
<template>
<img :src="`${$assets}/logo.png`"/>
<p>path: {{$assets}}</p>
</template>
<script>
export default {
mounted() {
console.log(this.$assets);
}
}
</script>

load them in created, mounted or where you need them
async created() {
try {
this.icon = (await import('#assets/images/img.png')).default;
} catch (e) {
// explicitly ignored
}
and then
<img :src=icon />

Inside code you can directly require image using.
const src = require("../../assets/images/xyz.png");
Or
In order to dynamically load image need this.
const image = new window.Image();
image.src = require("../../assets/images/xyz.png");
image.onload = () => {
// do something if needed
};

Related

Why loading dynamically assets fails on Nuxt v3

I'm experience a weird situation,
I have a "standard" Nuxt v3 project that comes with vite
Works
<img src="~/assets/img/image.png">
<img src="~/assets/video/video.mp4">
Does not work
<img :src="require('~/assets/img/image.png')">
<img :src="require('~/assets/video/video.mp4')">
Note that the image path is the same so it does exist, the error I'm getting is:
Cannot find module '#/assets/img/image.png' Require stack
The docs don't mention anything that has to be done in order to achieve it
Is there anything I should do?
You can't use require with vite and vite is nuxt3 default module bundler
There is two problem:
Nuxt will change assets directory and the file names after the build
aliases not convert to absolute path when you using it dynamically
So you can't do this even:
<img :src="`_nuxt/assets/img/${imageName}`">
it works in dev mode but not after the build.
Solution 1
you can import images and then use them like this:
<script lang="ts" setup>
//#ts-ignore
import image1 from "../assets/images/image1.jpg";
//#ts-ignore
import image2 from "../assets/images/image2.jpg";
//#ts-ignore
import image3 from "../assets/images/image3.jpg";
const images = [ image1, image2, image ]
</script>
Solution 2
I found this way:
<script>
const glob = import.meta.glob("~/assets/images/how-to-use/*", {
eager: true,
});
const getImageAbsolutePath = (imageName: string): string => {
return glob[`/assets/images/how-to-use/${imageName}`]["default"];
};
</script>
You can pass your imageName (don't forget the extension) to this function and get the absolute path.
This way works even after the build.
Solution 3
you can put your images to public directory
learn more: https://nuxt.com/docs/getting-started/assets/#public-directory
The public/ directory content is served at the server root as-is.

Vue 3: defineAsyncComponent not resolving .vue files and not splitting chunks

I'm trying to load Vue 3 components in a asynchronous way. I've found that there is a function called
defineAsyncComponent
which is supposed to be used as follows:
const GameUI = defineAsyncComponent(()=>import(filePath));
app.component("GameUI", GameUI);
filePath in this context is exactly: './components/GameUI/GameUI.element.vue'
Running the app like this leads to the following error:
Uncaught (in promise) Error: Cannot find module './components/GameUI/GameUI.element.vue'
at eval (eval at ./src lazy recursive)
But... if I change the filePath code to import the path as a string:
const GameUI = defineAsyncComponent(()=>import('./components/GameUI/GameUI.element.vue'));
The app works, it does find the component.
I don't want to use constant strings, because I have a lot of components and I want to load them asynchronously.
One of my main goals to achieve this, is to load the webapp by parts, component by component whenever they are needed, instead of loading them all on start.
I've also find that if I append a comment as follows:
const GameUI = defineAsyncComponent(()=>import(/* webpackChunkName: "GameUI" */ './components/GameUI/GameUI.element.vue'));
The JavaScript part for the GameUI component, should have it's own chunk.js file, but I always keep getting everything in a couple .js chunk files, which contradicts the async loading I want to achieve.
I'm using vue-cli-service, and my vue.config.js looks like this:
module.exports = {
productionSourceMap: false,
css: {
loaderOptions: {
sass: {
additionalData: process.env.NODE_ENV === 'production'
? '$baseURL:"/dist/";'
: '$baseURL:"/";'
}
}
},
publicPath: process.env.NODE_ENV === 'production'
? '/dist/'
: '/',
devServer: {
https: true,
port:"",
host:'website.com',
disableHostCheck: true,
cert: (fs.readFileSync('cert.pem')+""),
key: (fs.readFileSync('privkey.pem')+""),
ca: (fs.readFileSync('ca.pem')+""),
}
};
I've already tried multiple stuff I've found online, but they are not that much explanatory. I'm literally doing the same as some online articles I've found and cannot find the problem on my side.
The two main problems are:
Cannot load .vue files from variables, only full strings.
Cannot split the code into different .js files for every async loaded component.
The answer to the first question:
Because there have some limitations of async import
.
What you are doing cannot work because you are using a variable as value to defineAsyncComponent.
According to the limitations of async import, you cannot import your component usinig a variable. Instead what you can do is:
// If the component name to call is GameUI.element
const component = 'GameUI.element' // can be comed from anyting
const GameUI = defineAsyncComponent(()=>import(`./components/GameUI/${component}.vue`));
app.component("GameUI", GameUI);

How to fetch files from CDN with NuxtJS content module?

I want to fetch files from another server (e.g. a CDN) with the #nuxtjs/content module so that the .md files can be managed independently without Nuxt.js.
My current nuxt.config.js file looks like this:
export default {
...
content: {
dir: 'http://some-cdn.xyz/content/'
},
...
}
Now I want to load the content in the pages/_slug.vue file:
<template>
<div>
<NuxtContent :document="doc" />
</div>
</template>
<script>
export default {
async asyncData({ $content, params }) {
const doc = await $content(params.slug || 'index').fetch();
return { doc };
},
};
</script>
Now when I type in http://localhost:3000/some-page, I should get the corresponding file (some-page.md) from the CDN. Instead, I get this error from Nuxt.js: /some-page not found.
What should I do to get it working and is this even possible with my current setup?
As told here: https://github.com/nuxt/content/issues/237
This is not doable with the content module and is not planned to be done neither. A solution would be to manually fetch the files during the build time or alike.
You can maybe get some inspiration from this comment: https://github.com/nuxt/content/issues/37#issuecomment-664331854 or use another markdown parser.
Since #nuxtjs/content can't fetch files from another server, I used the marked.js library instead.

Angular4 - Use a function inside a JavaScript file

I'm trying to load a JavaScript file into my angular component. I have loaded the full minified version from here: https://github.com/blueimp/JavaScript-Load-Image/blob/master/js/load-image.all.min.js and also put any related scripts in my scripts folder.
When the code runs and reaches 'loadImage', the console fires an error:
ERROR ReferenceError: loadImage is not defined
What's the best way to resolve this?
Component
import '../../../assets/scripts/load-image.all.min.js';
declare var loadImage: any;
...
dropChangeHandler(e) {
e.preventDefault()
e = e.originalEvent
var target = e.dataTransfer || e.target
var file = target && target.files && target.files[0]
var options = {
maxWidth: 1000,
maxHeight: 1000,
canvas: true,
pixelRatio: window.devicePixelRatio,
// downsamplingRatio: 0.5,
orientation: true
}
if (!file) {
return
} else {
this.currentFile = file;
if (!loadImage(file, this.updateResults, options)) {
}
}
}
I think this question is slightly different to the other 'import JS files into angular' because I have a feeling it might be to do with the library I'm trying to import. However, I'm unsure and seeking advice on this one.
The library you are trying to import doesn't support es6 modules. Because of no exports in the library, it doesn't add any variables to your scope after import.
In your particular case easiest is to add the script to index.html:
<script src="assets/scripts/load-image.all.min.js"></script>
and call a method in the component with
window.loadImage(file, this.updateResult, options)
I use window because library directly binds itself to window.object
More details
To use javascript modules with typescript add allowJs: true to tsconfig.js file.
import './file is known as an import for side-effects only and don't change the scope of the module, but can access to global app scope. It can help you in case you want to extend already imported module.
You could import js module different ways:
For CommonJs modules it's possible to use import * as ModuleName from './modulePath.js'; in your component.ts file and call as ModuleName.exportedMethod().
to the Angular pipeline to be sure it is loaded with the module which
imports it. If you are using angular cli, simply include it to you
angular-cli.json in the section apps/scripts:
{
"apps":
...
"scripts": [
"assets/scripts/load-image.all.min.js"
]
}
If you don't use angular-cli, you can include to your index.html:
<script src="assets/scripts/load-image.all.min.js"></script>
I think you need to export the wanted function in your imported file.
you must unsusure that the library is will be compiled
Add the script in angular-cli.json
"scripts": [
....
'<path to file>/assets/scripts/load-image.all.min.js'
....
]
then
declare var loadImage: any;

ReactJS and images in public folder

Im new in ReactJS and I want to import images in a component. These images are inside of the public folder and I do not know how to access the folder from the react component.
Any ideas ?
EDIT
I want to import an image inside Bottom.js or Header.js
The structure folder is:
I do not use webpack. Should I ?
Edit 2
I want to use webpack for loading the images and the rest of assets. So in my config folder I have the next files:
Where I need to add the paths of the images and how?
Thanks
You don't need any webpack configuration for this.
In your component just give image path. React will know its in public directory.
<img src="/image.jpg" alt="image" />
To reference images in public there are two ways I know how to do it straight forward.
One is like above from Homam Bahrani.
using
<img src={process.env.PUBLIC_URL + '/yourPathHere.jpg'} />
And since this works you really don't need anything else but, this also works...
<img src={window.location.origin + '/yourPathHere.jpg'} />
the react docs explain this nicely in the documentation, you have to use process.env.PUBLIC_URL with images placed in the public folder. See here for more info
return <img src={process.env.PUBLIC_URL + '/img/logo.png'} />;
1- It's good if you use webpack for configurations but you can simply use image path and react will find out that that it's in public directory.
<img src="/image.jpg">
2- If you want to use webpack which is a standard practice in React.
You can use these rules in your webpack.config.dev.js file.
module: {
rules: [
{
test: /\.(jpe?g|gif|png|svg)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 10000
}
}
]
}
],
},
then you can import image file in react components and use it.
import image from '../../public/images/logofooter.png'
<img src={image}/>
Create a folder in public ex.Assets and put your image in that folder and assign the folder_name / image_name in src
<img src = "/Assets/cardimg.svg" alt="Card image cap" width="400" />
We know React is SPA. Everything is rendered from the root component by
expanding to appropriate HTML from JSX.
So it does not matter where you want to use the images. Best practice is to use an absolute path (with reference to public). Do not worry about relative
paths.
In your case, this should work everywhere:
"./images/logofooter.png"
Simply Use
<img src='/image.extension' />
React will automatically point toward the public directory
You should use webpack here to make your life easier. Add below rule in your config:
const srcPath = path.join(__dirname, '..', 'publicfolder')
const rules = []
const includePaths = [
srcPath
]
// handle images
rules.push({
test: /\.(png|gif|jpe?g|svg|ico)$/,
include: includePaths,
use: [{
loader: 'file-loader',
options: {
name: 'images/[name]-[hash].[ext]'
}
}
After this, you can simply import the images into your react components:
import myImage from 'publicfolder/images/Image1.png'
Use myImage like below:
<div><img src={myImage}/></div>
or if the image is imported into local state of component
<div><img src={this.state.myImage}/></div>
Try This One its easy and Simple
Don't Make Image folder in src.
Make an image folder in public.
you work in react-bootstrap install
npm install react-bootstrap
import React from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Image } from 'react-bootstrap';
export default function Main() {
return (
<>
<Image src="/img/image.jpg/100px250" alt="bg image" fluid />
</>
)
}
Hope it's Done
here is sure and three simple way to do that...
you can make one folder in directory and access it as we do import way or
you can give direct image name in src
<img src="image__name" alt="yourpic" />
//by default react look in public folder can render image in img tag
const image = window.location.origin + "/image.png";
// if your image in public directory inside folder imagecollection than you can import it in this way
const image = window.location.origin + "/imagecollection /image.png";
<img src={image} alt="yourpic" />
A simple solution is to use paths like this /images/logoFooter.png. If the file is located directly under the public folder, do /someImage.png. You can go deeper, /x/y/z/image.png. Treat the locating part of the image as an absolute kind of location for that image.
For more information, check out https://create-react-app.dev/docs/using-the-public-folder/.
if you want to add your javascript file from public folder to react, put specific file to index.html file in public folder. Your problem will be solve.
You Could also use this.. it works assuming 'yourimage.jpg' is in your public folder.
<img src={'./yourimage.jpg'}/>

Categories