Search code examples
javascriptdockervue.jswebpackvue-cli

Cannot create Vue application http-server - Error: css and js files 404 Not found


I want to dockerize my vue app, but when I run it in a docker container nothing is loaded in the browser.

Since I run CMD["http-server", "dist"] in my Dockerfile, I decided to test it out locally to troubleshoot the issue.

Running: npm run serve

Works fine and I get:

enter image description here

Then I run

npm run build

enter image description here

I believe this is due to having a posters folder with 50,000+ jpeg images in the assets directory which I dynamically display in the app as follows:

<div v-for="movie in this.recommendations" :key="movie" class="movie-card col-md-2">

 <img v-if="movie['poster']=='True'" :src="getImgUrl(movie['movieId'])" v-bind:alt="pic">

And the getImgUrl function is:

getImgUrl(imgName) {
            var images = require.context('../assets/posters', false, /\.jpg$/)
            return images('./' + imgName + ".jpg")
    }

vue/cli suggests

webpack performance recommendations: 
You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.
For more info visit https://webpack.js.org/guides/code-splitting/ 

but I'm not sure how to implement either one of these or if hosting the images on a public google drive and importing them from there would solve the issue?

Pretty new to vue so any help would be much appreciated!


Solution

  • By using the assets folder and using require you are bundling all of your images into your code, by encoding them as base64. So when it is compiled it is creating GIANT chunks. Because the images are compiled into the source.

    What you should do is move your images from assets to the public directory. Then load the images via HTTP. This means that your code and images remain separate. When the page loads, the browser requests the images separately from your code, and loads them into the file.

    For example

    <img v-if="movie['poster']=='True'" :src="getImgUrl(movie['movieId'])" v-bind:alt="pic">
    
    getImgUrl(imgName) {
         return `/posters/${imgName}.jpg`
    }
    

    Thus your directory structure would become

    -public
    -|--posters
    -|--|--Poster1.jpg
    -|--|--Poster2.jpg
    -|--|--Poster3.jpg
    -|--|--Poster4.jpg
    etc
    

    The public directory overly simplified acts as a webserver. Anything that is in it can be accessed directly. For example, if you were to move your images over, to the public directory, with the directory structure above, and access localhost:8080/posters/Poster1.jpg, it would load just the image, without even needing a Vue router.

    For a better, in-depth description of the public folder, and the role it serves check out the docs.