Webpack 4-复制dubdirectory结构

时间:2018-11-13 13:58:23

标签: webpack handlebars.js directory-structure

此刻,我有了Webpack 4和Handlebars结构

src/
├── assets/
│   ├── css/
│   ├── fonts/
│   ├── img/
│   ├── js/
│   ├── scss/
│   └── vendor/
├── helpers/
│   ├── repeat.js
│   └── compare.js
├── partials/
│   ├── header.hbs
│   └── footer.hbs
├── index.hbs
├── subpage1.hbs
└── subpage2.hbs

它很好地融合了

dest/
├── assets/
│   ├── css/
│   ├── fonts/
│   ├── img/
│   ├── js/
│   ├── scss/
│   └── vendor/
├── index.html
├── subpage1.html
└── subpage2.html

我可以接受,但客户端希望包含另一个index.html而不是subpage1.htmlsubpage2.html ...子文件夹/subpage1/等,以便他们可以使用漂亮的网址没有任何htaccess,并且正如他们所说的那样:-/

问题是如何复制子目录并处理其中的把手文件:

src/
├── assets/
│   ├── css/
│   ├── fonts/
│   ├── img/
│   ├── js/
│   ├── scss/
│   └── vendor/
├── helpers/
│   ├── repeat.js
│   └── compare.js
├── partials/
│   ├── header.hbs
│   └── footer.hbs
├── subpage1/
│   └── index.hbs
├── subpage2/
│   └── index.hbs
└── index.hbs

如果我成功完成此步骤,将面临另一个挑战-处理相对路径并使它们成为图像,css,bundle.js的绝对路径

这是我的webpack通用配置:

const path = require('path');
const webpack = require('webpack');
const handlebars = require('handlebars');
const utils = require('handlebars-utils');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const vars = require('./variables.js');
const glob = require('glob');

const generateHTMLPlugins = () =>
    glob.sync('./src/*.{html,hbs}').map(item => {
        return new HtmlWebpackPlugin({
            filename: path.parse(item).name + '.html', 
            template: item
        });
    });

module.exports = {
    context: vars.relativePath,
    entry: [
        vars.src.relativePath + vars.src.assetsPath + 'js/scripts.js'
    ],
    output: {
        path: vars.dist.relativePath,
        filename: vars.dist.assetsPath + 'js/bundle.js'
    },
    plugins: [
        new webpack.LoaderOptionsPlugin({
            options: {
              handlebarsLoader: {}
            }
        }),
        new CopyWebpackPlugin([ // images folder
            {
                from: vars.src.relativePath + vars.src.assetsPath + 'img',
                to: vars.dist.relativePath + vars.dist.assetsPath + 'img'
            }
        ]),
        new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery',
            'window.jQuery': 'jquery',
            Popper: ['popper.js', 'default']
        }),
        ...generateHTMLPlugins()
    ],
    module: {
        rules: [
            {
                test: /\.js?$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            },
            {
                test: /\.hbs$/,
                loader: 'handlebars-loader',
                query: {
                    helperDirs: [vars.src.relativePath + 'helpers'],
                    partialDirs: [vars.src.relativePath + 'partials'],
                    precompileOptions: {
                        knownHelpersOnly: false,
                    },
                }
            },
            { // Compile and merge sass + css
                test: /\.s?css/,
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader,
                        options: {
                            sourceMap: (this.mode == 'production') ? false : true
                        }
                    },
                    {
                        loader: 'css-loader',
                        options: {
                            sourceMap: (this.mode == 'production') ? false : true
                        }
                    },
                    {
                        loader: 'postcss-loader',
                        options: {
                            plugins: [
                                require('autoprefixer'),
                                require('cssnano')({
                                    discardComments: { removeAll: true }
                                }),
                            ],
                            sourceMap: (this.mode == 'production') ? false : true
                        }
                    },
                    {
                        loader: 'sass-loader',
                        options: {
                            sourceMap: (this.mode == 'production') ? false : true
                        }
                    }
                ]
            },
            { // Fonts
                test: /\.woff($|\?)|\.woff2($|\?)|\.ttf($|\?)|\.eot($|\?)|\.svg($|\?)/,
                exclude: /img\//,
                use: {
                    loader: "file-loader",
                    options: {
                        name: '[name].[ext]',
                        publicPath: '../fonts/',
                        outputPath: vars.dist.assetsPath + 'fonts/',
                    }
                },
            },
            { // Context images
                test: /\.(jpe?g|png|gif|svg)/,
                exclude: /font/,
                use: {
                    loader: "file-loader",
                    options: {
                        name: '[name].[ext]',
                        publicPath: '../img/',
                        outputPath: vars.dist.assetsPath + 'img/'
                    }
                }
            },
        ]
    }
};

Webpack变量:

const path = require('path');
const relativePath = path.resolve(__dirname, '../');
const argv = require('yargs').argv;
const theme = (argv.name === undefined) ? 'default' : argv.name

module.exports = {
    relativePath: relativePath,
    dist: {
        path: 'dist/',
        relativePath: relativePath + '/dist/', 
        assetsPath: 'assets/'
        // assetsPath: 'assets/' + theme + '/'
    },
    src: {
        path: 'src/',
        relativePath: relativePath + '/src/', 
        assetsPath: 'assets/'
        // assetsPath: 'assets/' + theme + '/'
    }    
}

和生产配置

const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const AggressiveMergingPlugin = require('webpack/lib/optimize/AggressiveMergingPlugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const vars = require('./variables.js');

module.exports = merge(common, {
    output: {
        path: vars.dist.relativePath,
        filename: vars.dist.assetsPath + 'js/bundle.js'
    },
    mode: 'production',
    plugins: [
        new MiniCssExtractPlugin({
            filename: vars.dist.assetsPath + 'css/style.min.css',
            allChunks: true,
        }),
        new UglifyJsPlugin(), //minify everything
        new AggressiveMergingPlugin(), //Merge chunks
        new CleanWebpackPlugin([vars.dist.path],{
            root: vars.relativePath
        })
    ]
})

1 个答案:

答案 0 :(得分:0)

所以..我找到了一种解决方案..也许不是一个优雅的解决方案,但是它可行。这是用于递归hbs到html的,除了partials dir:

glob.sync('./src/**/*.{html,hbs}', {"ignore": ['./src/partials/*']} ).map(item => {
    return new HtmlWebpackPlugin({
        // filename: path.parse(item).name + '.html', 
        filename: path.resolve(__dirname, '../') + path.parse(item).dir.replace('./src', '/dist') + '/' + path.parse(item).name + '.html', 
        template: item
    });
});

并最终为公众设置绝对路径

output: {
    path: vars.dist.relativePath,
    publicPath: '/',
    filename: vars.dist.assetsPath + 'js/bundle.js'
},