IncrediblePony
IncrediblePony

Reputation: 752

Webpack static file references in html template

I seem to be stuck. This may be a question that has been asked a million times before but I am at a point where I don't even know what to search for to get an answer. I apologize in advance.

I have a Webpack 4 VueJS 2 setup. I sorta works. Stuff compiles and the Webpack-dev-server can show me most of my site and holds a lot of the intended behaviour I expect. But... I cannot seem to get Webpack to inject files into my html template.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Kollecto</title>
    <link rel="icon" type="image/png" sizes="32x32" href="static/img/favicon-32x32.png">
    <link rel="icon" type="image/png" sizes="16x16" href="static/img/favicon-16x16.png">
    <!--[if IE]><link rel="shortcut icon" href="/static/img/icons/favicon.ico"><![endif]-->
    <!-- Add to home screen for Android and modern mobile browsers -->
    <link rel="manifest" href="static/manifest.json">
    <meta name="theme-color" content="#ffffff">

    <!-- Add to home screen for Safari on iOS -->
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="white">
    <meta name="apple-mobile-web-app-title" content="Kollecto">
    <link rel="apple-touch-icon" href="static/img/icons/apple-touch-icon-152x152.png">
    <!-- <link rel="mask-icon" href="<%= htmlWebpackPlugin.files.publicPath %>static/img/icons/safari-pinned-tab.svg" color="#ffffff"> -->
    <!-- Add to home screen for Windows -->
    <!-- <meta name="msapplication-TileImage" content="<%= htmlWebpackPlugin.files.publicPath %>static/img/icons/msapplication-icon-144x144.png"> -->
    <meta name="msapplication-TileColor" content="#ffffff">
    <!-- <% for (var chunk of webpack.chunks) {
        for (var file of chunk.files) {
        if (file.match(/\.(js|css)$/)) { %> -->
    <!-- <link rel="<%= chunk.initial?'preload':'prefetch' %>" href="<%= htmlWebpackPlugin.files.publicPath + file %>" as="<%= file.match(/\.css$/)?'style':'script' %>"><% }}} %> -->
</head>
<body>
    <style>
        <!-- inline styles.... -->
    </style>
    <noscript>
        This is your fallback content in case JavaScript fails to load.
    </noscript>
    <div id="app">
    <div class="spinner-container">
        <svg class="spinner" width="65px" height="65px" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg">
        <circle class="path" fill="none" stroke-width="6" stroke-linecap="round" cx="33" cy="33" r="30"></circle>
        </svg>
    </div>
    </div>
    <!-- Todo: only include in production -->
    <!-- <%= htmlWebpackPlugin.options.serviceWorkerLoader %> -->
    <!-- built files will be auto injected -->
</body>
</html>

This is an attempt of a migration from Webpack 3 to 4 with VueJS included. Here is my webpack.common.js

'use strict';

const helpers = require('./helpers');
const path = require('path');

const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
    entry: {
        polyfill: '@babel/polyfill',
        main: path.resolve(__dirname, '../src/main.js'),
        vendor: path.resolve(__dirname, '../src/vendor.js')
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                include: [helpers.root('src')]
            },
            {
                test: /\.html$/,
                use: [
                    'html-loader'
                ]
            },
            {
                test: /\.(svg|jpe?g|gif|png)$/,
                use: {
                    loader: 'file-loader',
                    options: {
                        name: '[name].[hash].[ext]',
                        outputPath: 'static/img'
                    }
                }
            },
            {
                test: /\.(ttf|eot|woff2?|otf)$/,
                use: {
                    loader: 'file-loader',
                    options: {
                        name: '[name].[hash].[ext]',
                        outputPath: 'static/fonts'
                    }
                }
            },
            {
                test: /\.ico$/,
                use: {
                    loader: 'file-loader',
                    options: {
                        name: '[name].[hash].[ext]',
                        outputPath: 'static/img/icons'
                    }
                }
            },
        ]
    },
    plugins: [
        new VueLoaderPlugin(),
    ]
};

And of course my webpack.dev.js

'use strict';

const webpack = require('webpack');
const path = require('path');
const common = require('./webpack.common');
const merge = require('webpack-merge');
const fs = require('fs')
const helpers = require('./helpers');

const HtmlWebpackPlugin = require('html-webpack-plugin');
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');

module.exports = merge(common, {
    mode: "development",
    resolve: {
        extensions: [ '.js', '.vue' ],
        alias: {
            'vue$':'vue/dist/vue.runtime.js',
            '@': helpers.root('src')
        }
    },
    devServer: {
        port: 9000,
        hot: true,
        open: true,
        overlay: true,
        stats: {
            normal: true
        }
    },
    output: {
        filename: `[name].bundle.js`,
        path: path.resolve(__dirname, "dist")
    },
    optimization: {
        runtimeChunk: 'single',
        splitChunks: {
            chunks: "all"
        }
    },
    plugins: [
        new HtmlWebpackPlugin({
            filename: helpers.root('index.html'),
            template: helpers.root('index.html'),
            inject: true,
            serviceWorkerLoader: `<script>${fs.readFileSync(path.join(__dirname,
                './service-worker-dev.js'), 'utf-8')}</script>`
        }),
        new webpack.EnvironmentPlugin({NODE_ENV: 'development'}),
        new webpack.HotModuleReplacementPlugin(),
        new FriendlyErrorsPlugin()
    ],
    module: {
        rules: [
            {
                test: /\.(scss|sass)$/,
                use: [
                    "style-loader", 
                    "css-loader", 
                    "sass-loader"
                ]
            },
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    'css-loader'
                ]
            }
        ]
    }
});

I hope somone has sharper eyes than me. Because I cannot seem to get icon files and scripts injected into my template. I know the index.html is commented and outcommented etc. But this is what I have. And I need help. Please :) More code can be provided if needed. (guide I followed: https://medium.com/js-dojo/how-to-configure-webpack-4-with-vuejs-a-complete-guide-209e943c4772)

Upvotes: 1

Views: 2234

Answers (1)

IncrediblePony
IncrediblePony

Reputation: 752

It turns out that webpack completely ignores the static folder in a project unless explicitly told so. This have resulted in me adding the CopyWebpackPlugin to my prod/staging builds as follows:

new CopyWebpackPlugin([
    {
        from: path.resolve(__dirname, '../static'),
        to: 'static',
        ignore: ['.*']
    }
])

This fixed my problem. All I had to do from there was make my loaders and bundles look for the correct files. The static folder is a 1 to 1 copy of your static folder on your applications root directory.

Upvotes: 1

Related Questions