Webpack 4-复制复制目录结构



现在我有了这个Webpack4&把手结构

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

我同意,但客户希望有subpage1.htmlsubpage2.html。。。子文件夹/subpage1/等包含另一个index.html,这样他们就可以在没有任何htaccess的情况下拥有漂亮的url,而且正如他们所说的那样,它更可读:-/

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

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
})
]
})

所以。。我找到了一个解决方案。。也许不是一个优雅的,但它是有效的。这是为递归hbs到html除了部分目录:

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'
},

最新更新