настройка Webpack - vue, babel, stylus, pug

У проекта следующая структура: два типа компонентов, vue и папки с pug/js/styl; index.pug есть главным файлом, который компилируется в index.html и index.pug наслдует layout.pug включает другие pug, как head.pug в котором есть main.js скрипт с импортами других скриптов. index.pug может включать в себя контейнер div для main .vue компонента, так и для других .pug and .vue которые, в свою очередь,могут быть заполненны .vue или .pug компонентами.

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

-- .pug, .js, .styl папки компонентов

-- .vue компоненты

Не могу настроить webpack для нормальной компиляции файорв в dist: index.html, error.html, /scripts/bundle.js, /styles/main.css.

static-dist/index.html получается пустым или заполненным JS кодом. То есть не компилируются нормально .pug и каша в других частях, относящихся к vue, styl, pug. Как исправить?

//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;

В самом проекте минимум статики для клиента html/js/css для dist/production и остальное компилируется сервером и отдается по запросу, например, если есть запрос страницы "about", нужный компонент страницы загружается с сервера в скомпилированном виде, то есть сервер берет .vue или pug/js/styl страницу/компонент, компилирует и дает статику клиенту.


Ответы (0 шт):