Vue.js - Why should I put images on /assets instead of putting them directly in /public - vue.js

When I use the #vue/cli to create a vuejs project, I see that there is a folder /assets that contains images and whatever I want. Than they can be referenced in the html such as <img src="#/assets/images/home.png" /> or import it on the js part.
My question is, why can't I just put the assets in /public/assets and put directly <img src="/assets/images/home.png" /> in my code? Where is the advantage of these assets?

It allows Webpack to handle assets, which means it can merge/minify files (useful for JS and CSS), optimize images, and more importantly version them so that cache handling is improved.

Related

How to make the path auto in the components in vue?

If I use a component in different path.the images in the component can not auto fix the path.
for example:
<img src="../icon.png" /> in the folder wwwroot is ok.
but if there is another html detail.html in the wwwroot/detail folder.
it is <img src="../../icon.png" /> also will be ok.
but it can not auto fix the path. need I specify the path as a variable every time?
I am not using the node and vue cli just vue single page.
You need to use an absolute path to the resource. An absolute path begins with / and will always point to the same location regardless of the location of the webpage.
Assuming you have wwwroot/detail/icon.png in your filesystem and wwwroot is hosted at the root, then you can reference the image like this:
<img src="/detail/icon.png">

How to convert *.vue example files for CDN use?

I am looking at the example files of vuetify. They all seem to be *.vue files. I am only familiar with *.html *.css *.js files where vue is used with CDN. How to convert/modify these vue files for CDN use? what are the steps? What are the pitfalls in doing so?
I am a beginner in vue.js and currently prototyping a tiny application to input/output few data and nothing fancy is required. CDN fits well for that.
So at first I would always recommend going with the Vue CLI instead of the CDN usage because it brings you a lot of benefits and a overall smoother developer expierence.
Coming to your question: Here is the starter template for Vuetify with a CDN https://codepen.io/pen?template=OJJeVge
They simply use the vuetify components inside a <script> tag with an id and mount that and initialize the vue instance with it.
You would put all other data stuff inside the <script> tag like you would do inside the script tag of a normal .vue file.

VueJS & v-html: How do I prepend the baseURL to asset links in imported HTML?

Apologies if this explanation isn't super clear. I am new to VueJS and I will do my best to explain my predicament.
I am building an application that imports html from external files into a component using v-html. I achieved that without any problems. However, the html has a bunch of asset urls that start with a /. What I want to do is to ensure that every asset url that starts with a / has a baseURL placed in front of it, converting it from say '/some-folder/some-asset.jpg' to '../../static/some-folder/some-asset.jpg' automatically without me having to programmatically modify the url.
I have tried modifying settings in the configuration file index.js, namely by trying different urls in assetsSubDirectory and assetsPublicPath but without success.
This is an example of a node in the imported html:
<picture>
<source media="(min-width: 768px)"srcset="/media/3974/cover_tablet.jpg">
<img id="img_20921" src="/media/3973/cover-mobile.jpg" class="img-fluid">
</picture>
I am trying to change the src value of:
/media/3974/cover_tablet.jpg
to:
../../static/media/3974/cover_tablet.jpg
by setting a base URL in the vue configuration but it won't prepend ../../static to the url and therefore the app cannot find the relevant asset.
The only way I managed to get this to work is by using JQuery to look for "src:" strings in the imported html and then prepend the baseURL into the link. This isn't at all ideal though and what I really want to achieve is for any link that starts with a "/" to have the apps baseURL prepended to it automatically.
I am starting to wonder if it is even possible for urls in imported html to pick up the apps baseURL value?
I found a solution. I was using the webpack template for my project which proved to make this particular issue difficult to work out so I reset my project using the Vue CLI template instead, put all my assets in the public folder and all the links in my imported html were picked up immediately with no fuss and no messing around with webpack configuration.

vue access to images

I'm trying to view an image in one of my pages. I'm on a latest node-express-vue-nuxt-babel setup. My final goal was:
<img :src="'#/assets/images/projects/' + project.image" width="50px" />
I started with the above, but I got a 404. So I tried with a specific image:
<img src="#/assets/images/projects/5a2db62e346c1.jpg" width="50px" />
and it worked, but going back to dynamic source didn't and:
to <img :src="'#/assets/images/projects/5a2db62e346c1.jpg'" width="50px" />
was enough to produce the 404 again. The 404 was in the console, the page was loading fine with no errors but alas no signs of the image(s). Inspecting the elements made me notice that the dynamic :src became:
<img src="#/assets/images/projects/5a2db62e346c1.jpg" width="50px" />
and the 'static' src became:
<img src="/_nuxt/assets/images/projects/5a2db62e346c1.jpg" width="50px" />
So to make it work I had to renounce to the initial "#" and substitute it with "_nuxt":
<img :src="'_nuxt/assets/images/projects/' + project.image" width="50px" />
Ok, nice, but.. why?
Do this: <img :src="require('#/assets/images/projects/' + project.image)"/>
VueJs
There are several asset URL transforms rules in vuejs. Here is one of them:
If the URL starts with #, it's also interpreted as a module request. This is useful if your webpack config has an alias for #, which by default points to /src in any project created by vue-cli
For more information : Asset URL
You are using webpack for bundling the application.
At a very high level webpack looks for require and takes care of bundling your scripts. Exactly what that means depends on your specific configuration, but it usually gathers all the js files in one file, usually minifies and removes unused code.
Webpack is not limited to js files. By the use of plugins it can handle extracting images from html files, load resources from urls and much more.
The way it ends up loading images is still by the use of require, the plugins just plug everything in so webpack can handle them. That being said, require is a compile time feature and if the path can't be determined at compile time webpack will not work. Webpack will usually translate the image path to a path that's available at runtime (usually they are different and depend on your webpack config).
When you bind src like this:
:src="'#/assets/images/projects/' + project.image"
The path can't be determined at compile time and as such vue will resolve it at run time, but webpack already finished and it will not translate your path.
There are a couple of ways to handle this:
As you found out: using a static runtime path, that is not handled by webpack, will work. The downfall is that if you change the way you build your project you'll need to update all references (in your case _nuxt). Note: if using vue.cli, you usually get a folder called static that is used exactly for this.
Use a binding, but bind to the run time path. This has the same downside as above and also the following: webpack has cache-busting technics that mangle file names, so knowing the final name of an asset that is handled this way by webpack is virtually impossible.
It worked also with backticks:
<img :src="require(`#/assets/images/projects/` + project.image)" width="100px" />
Thanks guys!

What files do webpack loaders work through?

When you set the regex after the test key in a loader object, does that look through all files in your project and load them using the loader you've designated, even if those files weren't required by the file in your entry point? Does this then get placed in the bundle.js file?
No it will only include what is required by your script.
<img src={ require('../some/img.png') } /> is a way to tell Webpack that your source code needs this image to run.
In a production Webpack build, this will get compiled into something like <img src="http://yoursite/whatever/89de0f2.png" />. The require() statement is never executed, it's replaced with valid Javascript code. This replaced code is what's put in bundle.js.
The image is then put into whatever output folder you specify (like a local dist/ folder), and it's renamed to something unique, which is usually some hash of the file contents, resulting in 89de0f2.png. (I made up this name for the example, but it usually looks something like that).
Now when you upload that file, 89de0f2.png, your source code will reference 89de0f2.png exactly, so that version of the image is guaranteed to exist. This is how Webpack gives you production guaranteed asset loading.
Wepback will only put img.png in your dist/ folder as 89de0f2.png if you specifically require it. Any other images will not be put in that folder.
You may also be asking about base64 encoding images and putting them directly into your bundle.js file. In this case, no image is put into dist/, but all the other rules reply. The require() call is still replaced with valid Javascript.
There is one case where Webpack will require multiple assets. You can require patterns, like <img src={ require.context( './images', true, /\.png/ ) } /> and Webpack will build all png files in that directory into the dist/ folder. See this Stackoverflow question for more context.