5

Im getting started with webpack but one thing I cannot for the life of me work out is how to take a folder (with possible nested folders), full of .pug templates, and simply compile them to static html and put them in the output folder, maintaining any nested folder structure for each output html file that was in the source templates folder...

I dont want to have to manually specify each individual .pug file, and I definitely dont want webpack to try and parse the .pugs into JS and then attempt to require/import any of the imgs/fonts etc in the pug files and then complain about it, Im just after a basic, static 1:1 compile, pug file in, html file out. Why is it so hard to do that?

Graham
  • 7,431
  • 18
  • 59
  • 84
Matthew
  • 952
  • 7
  • 20
  • it is possible with webpack but it is easier to use `gulp` if you are not mainly dealing with js files – Bryan Chen Feb 19 '17 at 23:31
  • id rather not add gulp and its dependencies into every project as well... you say its possible with webpack, could you elaborate? – Matthew Feb 20 '17 at 00:37
  • show your existing webpack config. you can use `function requireAll (r) { r.keys().forEach(r); } requireAll(require.context('./src', true, /\.pug$/));` to require every .pug files under src folder and configure `file-loader` to do the copy – Bryan Chen Feb 20 '17 at 00:42
  • i dont have to use extract text plugin in there somewhere? – Matthew Feb 20 '17 at 02:56
  • how does extract text plugin related to your question at all? – Bryan Chen Feb 20 '17 at 02:58
  • Heres a gist of my config: [webpack config gist link](https://gist.github.com/matthewjumpsoffbuildings/54aa7875c8ee2b35364550a857a79dbb) – Matthew Feb 20 '17 at 03:01
  • i want to save static html files from each pug file, i thought the extract text plugin was the way to do this? just like you have to use the extract text plugin to save .css files from the sass-loader, dont you have to use extract text to save .html files from pug-loader? – Matthew Feb 20 '17 at 03:16

2 Answers2

11

Use pug-html-loader to convert .pug to .html file. Use file-loader to copy the file to desired location. Don't use html-loader as you don't want to process resources used by the generated file.

You will end up something like this in your loader rules (untested, webpack 1 syntax, you may need to tweak it for webpack 2)

{
    test: /\.pug$/,
    loaders: ['file-loader?name=[path][name].html', 'pug-html-loader?pretty&exports=false']
}

Next you need to require all your pug files in your entry file

function requireAll (r) { r.keys().forEach(r); }
requireAll(require.context('./', true, /\.pug$/));
Bryan Chen
  • 45,816
  • 18
  • 112
  • 143
  • I have one other question - say i use this `require.context('./pug/', true, /\.pug$/)` so its looking in the pug folder, currently when i use the file-loader with the `name=[path][name].html` query parameter, the templates are getting put into a pug folder in my build directory. eg if a certain source pug template lives in `/pug/home/template.pug` I end up with `/dist/pug/home/template.html`, but I want it to be `dist/home/template.html` is there a way to control what [path] will output in the file-loader query string? – Matthew Feb 20 '17 at 15:22
  • 1
    try `file-loader?name=[path][name].html&context=./pug`, you may need to change the context parameter to make it work – Bryan Chen Feb 20 '17 at 21:36
  • Im back again with something else - using this method, in my main bundle.js I now have a bunch of entries for the pug files, even though they dont need to be in there - eg ```(function(module, exports, __webpack_require__) { module.exports = __webpack_require__.p + "layouts/default.html"; /***/ })``` how do i get rid of these? – Matthew Feb 21 '17 at 03:47
  • You can put the `requireAll` call to a new entry file and ignore the js output of it – Bryan Chen Feb 21 '17 at 04:04
  • ye i have a separate entry file for the pug stuff, how do i ignore the output of that entry file in the webpack.config.js? – Matthew Feb 21 '17 at 04:40
  • you can't really ignore it with webpack, but you can set it output path to some ignored folder or have a extra step to remove that file. but that won't be inside webpack – Bryan Chen Feb 21 '17 at 08:49
  • out of curiosity, when i use the ExtractTextPlugin for my scss/sass files, even though I have my main scss file as an entry point, no output bundle for that is generated... so it seems that plugins can take entry points and not emit a bundle for any imports/requires that match it? is there perhaps some kind of null plugin that I can use to stop webpack emitting a bundle file for the pug requires? – Matthew Feb 21 '17 at 14:37
  • It is possible but I never used anything like before. You can ask a new question and maybe someone else can help you. – Bryan Chen Feb 21 '17 at 20:33
  • thanks, yea i asked a new question. also im an idiot - the extract text plugin *was* outputting a bundle.css :/ – Matthew Feb 21 '17 at 20:35
  • @ByranChen, sorry to bother you again, I have one other question with the pug templates - Im trying to pass the webpack hash into the pug templates so it can be used in `script(src="bunde.${HASH}.js")` etc... I have a separate question [posted here](https://stackoverflow.com/questions/42404303/webpack-insert-hashed-bundle-urls-into-static-pug-templates) but its got no comments for ages, any advice? – Matthew Mar 07 '17 at 17:19
1

This can be done very simply with only html-webpack-plugin and pug-loader.

webpack.config.js

const HTMLWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  // No javascript entrypoint to evaluate. Let the plugin do the heavy lifting
  entry: {},
  // Translate Pug to HTML
  module: { rules: [ { test: /\.pug$/, use: 'pug-loader' } ] },
  // Save HTML to file
  plugins: [ new HTMLWebpackPlugin({ template: './src/index.pug' }) ]
};

./src/index.pug

doctype html
html(land="en")
  head
    include path/to/another.pug
...

Got this information from https://extri.co/2017/05/23/using-htmlwebpackplugin-and-pug/ and you can also go further to import css and javascript as normally done with html-webpack-plugin.

RWDJ
  • 734
  • 8
  • 13
  • You saved my life I'm trying something like this. But when I didn't define the `entry: {}` it kept trying to find an `index.pug` file in the src because of the loader and the resolve `.pug` – codermarcos Sep 16 '22 at 18:58