0

My project has the following structure: two types of components, vue and folder with pug/js/styl; index.pug is the main file that is to be index.html and index.pug extends layout and includes other pug, like head.pug that has the main.js script with imports of other required scripts. index.pug may also include a div container for main .vue component just like other .pug and .vue files are to be populated with either .vue or .pug components.

-index.pug <= layout,head .pug, main.vue, main.js, main.styl

-- .pug, .js, .styl folder-components

-- .vue components

I can not configure webpack properly to have index.html, error.html, /scripts/bundle.js, /styles/main.css static-dist/index.html is empty or filled with JS code. So it cannot properly compile .pug and there is a mess with other parts related to vue, styl, pug. How to fix that all?

//const webpack = require('webpack');
const path = require('path');
const PugPlugin = require('pug-plugin');
const { VueLoaderPlugin, default: loader } = require('vue-loader')
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const threadLoader = require('thread-loader');
const autoprefixer = require('autoprefixer-stylus')


const devMode = process.env.NODE_ENV !== "production";
const PATHS  =  {
    dist:  path.resolve(__dirname, 'client-dist'),
};
threadLoader.warmup(
    {
      // pool options, like passed to loader options. must match loader options to boot the correct pool
    },
    [ // modules to load. can be any module, i. e.
      'babel-loader',
      'stylus-loader',
    ]
  );

const config = {
    entry: {
        // The Pug file is the entry point for all scripts and styles. Source scripts and styles must be specified directly in Pug.
        //error: './views/error.pug',      // output to client-dist/index.html
        index: './views/index.pug', 
        //script: path.join(__dirname + '/scripts/scripts.js'),
        //'pages/page': './views/index.pug', 
    },
    output: {
        path: path.resolve('../client-dist'), //path.join(`${__dirname}`, `/../client-dist`),
        filename: `scripts/bundle-[name].[contenthash:8].js`,
        publicPath: '/' ,// public URL of the output directory when referenced in a browser
        compareBeforeEmit: true, // true: will not write output file when file already exists on disk with the same content.
        clean: true,
    },
    resolve: {
        extensions: [".js", ".vue", ".css", "styl", "pug", "html"],
    },
    mode: 'development',
    devtool: (devMode ? '#source-map' : false),
    //devtool: 'eval-cheap-module-source-map',
    cache: true,
    
    module: {
        rules: [
            {
                test: /\scripts.js$/,
                exclude: file => ( /(node_modules|env_sr)/.test(file) && !/\.vue\.js/.test(file) ),
                use: [
                    {
                        loader: 'babel-loader',
                        options: {
                            presets: ['@babel/preset-env'],
                            plugins: ['@babel/plugin-transform-runtime'],
                            cacheDirectory: true,
                        }
                    },
                    {
                        loader: 'thread-loader',
                        options: {
                            workers: 2,
                        }
                    },
                    {
                        loader: "source-map-loader",
                        //enforce: "pre"
                    },
                ]
            },
          /*{ loader: "style-loader",  // creates style nodes from JS strings },
            { loader: "css-loader", // translates CSS into CommonJS
                options: { sourceMap: true, }, },*/
            {
                test: /\.css$/i,
                use: [ MiniCssExtractPlugin.loader, "vue-style-loader", "css-loader"], //, "stylus-loader"
            }, 
            {
                test: /\.vue$/i,
                use: ["vue-loader"]
            },
            {
                test: /\.vue\.(styl)$/,///\.vue$/i,
                sideEffects: true,
                //loader: 'vue-loader',
                use: ["vue-style-loader", "css-loader", {//"vue-loader", 
                    loader: 'stylus-loader', options: {
                        stylusOptions: {
                            includeCSS: false,
                            resolveURL: true,
                            lineNumbers: false,
                            hoistAtrules: true,
                            compress: true,
                            sourceMap: true,
                            outputPath: "/styles/",
                            publicPath: "/styles/"
                        }
                    },
                }, //autoprefixer(),z
                ], //, "stylus-loader"
            }, 
            {
                test: /\.styl(us)?$/,
                exclude: /node_modules/,
                sideEffects: true,
                use:
                [
                    { loader: 'resolve-url-loader' },
                    MiniCssExtractPlugin.loader,
                    //{ loader: 'vue-style-loader' },
                    { loader: 'css-loader' },
                    //{ loader: 'resolve-url-loader' },
                    {
                        loader: 'stylus-loader',
                        options: {
                            stylusOptions: {
                                use: ["nib" /* , autoprefixer() */],
                                include: [path.join(__dirname, "styles/")],
                                import: ["nib", path.join(__dirname, "styles/helpers/*")],
                                define: [
                                    ["$development", process.env.NODE_ENV === "development"],
                                    ["$production", process.env.NODE_ENV === "production"],
                                ],
                                includeCSS: false,
                                resolveURL: true,
                                lineNumbers: true,
                                hoistAtrules: true,
                                compress: true,
                                sourceMap: true,
                                outputPath: "/styles/",
                                publicPath: "/styles/"
                            }
                        },
                    }, autoprefixer(),
                  /*{  loader: "style-loader", }, { loader: "css-loader", }, { loader: "stylus-loader", }, */
                ] /*   vue-style-loader', 'stylus-loader'], options: { stylusOptions: {} } */
            },
            {
                test: /\.pug$/i,
                exclude: /node_modules/,
                loader: 'vue-pug-loader',//PugPlugin.loader, // PugPlugin already contain the pug-loader //'vue-pug-loader
                oneOf: [
                    // this applies to `<template lang="pug">` in Vue components
                    {
                        resourceQuery: /^\?vue/,
                        use: ['pug-plain-loader'] // PugPlugin.loader
                    },
                    // this applies to pug imports inside JavaScript
                    //{ issuer: /\.(js)$/, use: ['raw-loader', 'pug-plain-loader'] },
                    {
                        use: [PugPlugin.loader
                            /* "html-loader",
                            "pug-html-loader" */
                        ]
                    }
                ],
            },
            {
                test: /\.(png|svg|jpg|gif)$/,
                use: [
                    {
                        loader: 'file-loader', //  resolves import/require() on a file into a url and emits the file into the output directory
                        options: {
                            name: '[name].[ext]',
                            outputPath: 'images',
                        },
                    }
                ],
            },
            {
                test: /\.(ttf|eot|woff|woff2|svg)$/i,
                use: {
                    loader: 'file-loader',
                    options: {
                        name: '[name].[ext]', // fonts/
                        outputPath: 'fonts',
                        publicPath: "fonts",
                    },
                },
            }
        ]
    },

    plugins: [
        // enable processing of Pug files defined in webpack entry
        new PugPlugin({
            js: { filename: 'scripts/[name].[contenthash:8].js', },
            css: { filename: './styles/[name].[contenthash:8].css', },
        }),
        new VueLoaderPlugin(),
        new MiniCssExtractPlugin({filename: './styles/[name].[contenthash:8].css'}),
        new CopyPlugin({
            patterns: [
              { from: `${__dirname}/images`, to: `${__dirname}/../client-dist/images` },
              { from: `${__dirname}/icons`, to: `${__dirname}/../client-dist/icons` },
              { from: `${__dirname}/fonts`, to: `${__dirname}/../client-dist/fonts` },
              { from: `${__dirname}/data`, to: `${__dirname}/../client-dist/data` },
            ],
        }),
    ],

    optimization: {
        minimizer: [
          // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
          // `...`,
          new CssMinimizerPlugin({
            parallel: true,
          }),
        ],
    }
};

if (!devMode) {
    config.plugins.push(
        // new UglifyJSPlugin(),
        /* new CopyWebpackPlugin([{ from: __dirname + '/src/public' }]) */
    );
};
/* if (process.env.NODE_ENV === 'test') {
    module.exports.externals = [require('webpack-node-externals')()]
    module.exports.devtool = 'inline-cheap-module-source-map'
} */

module.exports = config;

There is a minimum of html/js/css for dist/production static files and the rest is compiles on server and fetched upon a request, for instance, if "about" page is requested of a page component is to be loaded, a server gets a .vue or pug/js/styl page or component, compiles it and fetches the static code to client.

CodeGust
  • 831
  • 3
  • 15
  • 36

0 Answers0