Open lexcode opened 6 years ago
I'd love to know if you can do this or a glob pattern
For my task I decided so
const mix = require('laravel-mix');
const fs = require('fs');
const argv = require('yargs').option('env.html', {
default: false
}).argv;
class NunjucksMixPlugin {
register(src) {
this.src = src;
}
dependencies() {
this.requiresReload = true;
return ['nunjucks', 'nunjucks-webpack-plugin'];
}
webpackConfig(config) {
if (Config.production || !argv.env.html) {
return;
}
const NunjucksWebpackPlugin = require('nunjucks-webpack-plugin');
config.plugins.push(
new NunjucksWebpackPlugin({
templates: this.getAllTemplates()
})
);
}
getAllTemplates() {
const templates = [];
fs.readdirSync(this.src).forEach(file => {
if (file.indexOf('.njk') !== -1) {
templates.push({
from: `${this.src}/${file}`,
to: `html/${this.replaceFileExtension(file)}`
});
}
});
return templates;
}
replaceFileExtension(file) {
const pos = file.lastIndexOf('.');
return file.substr(0, pos < 0 ? file.length : pos) + '.html';
}
}
mix.extend('nunjucksPlugin', new NunjucksMixPlugin());
I end up doing this last year.
pages.js
/**
* Generate HTML Plugins
*/
const path = require('path');
const fs = require('fs');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const pages = {
generatePages: function generatePages(pagesPath) {
const names = [];
fs.readdirSync(pagesPath).map(file => {
const pageName = path.parse(file).name;
return names.push(pageName);
});
// console.log(names);
return names.map(
name =>
new HtmlWebpackPlugin({
// inject: 'body',
filename: `${name}.html`,
template: path.resolve(__dirname, `${pagesPath}/${name}.njk`),
}),
);
},
};
module.exports = pages;
Then in webpack.config.js
plugins: [
...pages.generatePages(path.resolve(__dirname, commonPaths.pagesPath)),
],
I rewrote the example from the last post for recursive traversal of directorie with templates.
pages.js
/**
* Generate HTML Plugins
*/
const path = require('path');
const fs = require('fs');
const NunjucksWebpackPlugin = require('nunjucks-webpack-plugin');
const directories = []
function walkDir(dir, parrent = '') {
var files = fs.readdirSync(dir)
for(var x in files){
var next = path.join(dir,files[x]);
if(fs.lstatSync(next).isDirectory()==true){
walkDir(next, parrent+'/'+files[x]);
}else{
directories.push([path.parse(files[x]).name, (parrent+'/').slice(1)])
}
}
return directories
}
const pages = {
generatePages: function generatePages(pagesPath) {
return walkDir(pagesPath).map(
name =>
new NunjucksWebpackPlugin({
templates: [{
from: `${pagesPath}/${name[1]}${name[0]}.njk`,
to: `${name[1]}${name[0]}.html`
}]
}),
);
}
};
module.exports = pages;
My webpack template - https://github.com/bnku/webpack-nunjucks-saas-template
@lexcode , @bnku
Both solution is really good, I was looking for the same solution for a while.
I tried, everything is fine, I have only one problem.
When I modify other files (e.g. src/templates/layout/layout.njk) it nothing happens, only when I modify page files (src/templates/pages/index.njk
or src/templates/pages/news.njk
).
Also when I add a new page, it doesn't generate into html, I need to rerun again.
Here is my structure:
And I'm calling like this:
plugins: [
...nunjuckspages.generatePages(path.resolve(__dirname, 'src/templates/pages')),
]
What do I need to do to trigger it whenever a file changes?
@levipadre use it for your structure:
plugins: [
...nunjuckspages.generatePages(path.resolve(__dirname, 'src/templates')),
]
I used about the following structure for my project:
Thank you @bnku! With this structure and path it is working indeed. Only one problem remains: the layouts folder and everything within it also have generated. How can I stop that?
@levipadre delete them in a separate script after the webpack is completed.
@bnku I just tried with https://www.npmjs.com/package/remove-webpack-plugin but the removed folder came back somehow. Like nunjucks runs after RemoveWebpackPlugin.
const RemoveWebpackPlugin = require('remove-webpack-plugin');
plugins: [
...nunjucksConfig.generatePages(path.resolve(__dirname, './src/templates')),
new RemoveWebpackPlugin('./pages/layouts/')
]
Probably not the best way, but I could manage with:
const paths = RemoveWebpackPlugin = require('remove-webpack-plugin');
const WebpackOnBuildPlugin = require('on-build-webpack');
plugins: [
...nunjucksConfig.generatePages(path.resolve(__dirname, paths.src.templates)),
new WebpackOnBuildPlugin(function(stats) {
new RemoveWebpackPlugin('./pages/layouts/')
})
]
Thank you all your help @bnku !
Anyone got a nice boilerplate that uses webpack 4, nunjucks and postcss?
For multiple templates, how to achieve it without specifying manually the files in webpack.config.js?
Thanks