Search code examples
javascriptwebpackwebpack-dev-servernunjucksbuild-tools

How to bundle Nunjucks files via Webpack


I have a complete site that I want to design a build tool for it.In fact, I chose Webpack for doing that. The project structure is like this:

enter image description here

I have nunjucks, html, css, sass and js files. I must bundle them via webpack. My webpack config file is here:

var HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const path = require('path')
const CopyPlugin = require('copy-webpack-plugin')
const NunjucksWebpackPlugin = require('nunjucks-webpack-plugin')

module.exports = {
    entry: ['./src/index.js'],
    output: {
       filename: 'bundle.js',
       path: path.resolve(__dirname, 'dist')
        },
    devtool: 'inline-source-map',
    devServer: {
        contentBase: './dist',
        writeToDisk: true
    },
   plugins: [
       new CopyPlugin([
           { from: 'public/images', to: 'images' },
           { from: 'public/fonts', to: 'fonts' },
           { from: 'src/pages/about', to: '.' }
         ]),
         new CleanWebpackPlugin(),
       // new HtmlWebpackPlugin()
        new HtmlWebpackPlugin({
           title: 'Asset Management' //title of file.html
         })
       ],
     module: {
        rules: [
           {
               test: /\.css$/,
               use: ['style-loader', 'css-loader']
            },
            {
               test: /\.s[ac]ss$/i,
               use: [
                // Creates `style` nodes from JS strings
                'style-loader',
                // Translates CSS into CommonJS
                'css-loader',
                // Compiles Sass to CSS
                'sass-loader'
            ]
          },
          {
            test: /\.(png|svg|jpg|gif)$/,
            use: ['file-loader']
          },
          {
            test: /\.(woff|woff2|eot|ttf|otf)$/,
            use: ['file-loader']
          },
          {
            test: /\.(njk|nunjucks)$/,
            loader: 'nunjucks-loader'
          },
         {
             // to auto refresh index.html and other html
             test: /\.html$/,
             loader: 'raw-loader',
             exclude: /node_modules/
         },
        {
            test: /\.html$/,
            use: [
                {
                    loader: 'html-loader',
                    options: {
                        interpolate: true
                    }
                }
            ]
        }
     ]
   }
  }

The "index.js" file also is like this:

  import _ from 'lodash'
  import './pages/about/about_moon.scss'
  import './pages/about/about_moon.html'
  var tpl = require('./pages/home/index_moon.njk')
  var html = tpl.render({ message: 'Foo that!' })
  function component() {
  return element
    }
   document.body.appendChild(component())

I configured the "package.json" file and defined scripts to run webpack:

    "start": "webpack-dev-server --open",
    "build": "webpack"

The problem is when I run npm run build, the dist folder was made and it had a html file but there is nothing to show. I have already had some html files and wanted to bundle all of them to "bundle.js", but I have not known how. Would you please tell me how I can bundle this project?

Thank you in advance.


Solution

  • Problem solved. I changed the Webpack.config.js file to this:

      const path = require('path')
      var HtmlWebpackPlugin = require('html-webpack-plugin')
      var UglifyJSPlugin = require('uglifyjs-webpack-plugin')
      const CopyPlugin = require('copy-webpack-plugin')
      const { CleanWebpackPlugin } = require('clean-webpack-plugin')
      const BrowserSyncPlugin = require('browser-sync-webpack-plugin')
      module.exports = {
           entry: ['./src/index.js', './script.js'],
           output: {
            filename: 'bundle.js',
            path: path.resolve(__dirname, 'dist')
          },
        plugins: [
        // HtmlWebpackPluginConfig
          new HtmlWebpackPlugin({
              filename: 'index.html',
               inject: 'head',
               template: './index.njk'
             }),
          new CleanWebpackPlugin(),
          new CopyPlugin([
            { from: 'public/images', to: 'images' },
            { from: 'public/fonts', to: 'fonts' }
          ])
         ],
        module: {
        rules: [
              {
                test: /\.exec\.js$/,
                use: ['script-loader']
              },
              {
                test: /\.css$/i,
                use: ['style-loader', 'css-loader']
              },
              {
                test: /\.(scss)$/,
                use: [
                    {
                     // Adds CSS to the DOM by injecting a `<style>` tag
                        loader: 'style-loader'
                    },
                    {
                        // Interprets `@import` and `url()` like `import/require()` and will resolve them
                        loader: 'css-loader'
                    },
                    {
                        // Loader for webpack to process CSS with PostCSS
                        loader: 'postcss-loader',
                        options: {
                            plugins: function() {
                                return [require('autoprefixer')]
                            }
                        }
                    },
                    {
                        // Loads a SASS/SCSS file and compiles it to CSS
                        loader: 'sass-loader'
                    }
                  ]
                },
              {
                // HTML LOADER
                // Super important: We need to test for the html
                // as well as the nunjucks files
                test: /\.html$|njk|nunjucks/,
                use: [
                    'html-loader',
                    {
                        loader: 'nunjucks-html-loader',
                        options: {
                            // Other super important. This will be the base
                            // directory in which webpack is going to find
                            // the layout and any other file index.njk is calling.
                            //  searchPaths: [...returnEntries('./src/pages/**/')]
                            // Use the one below if you want to use a single path.
                            // searchPaths: ['./']
                        }
                    }
                ]
            }
           ]
         }
        }
    

    Also, I wrote the script.js file like this, since, function names were changed and they could not be run after bundling.

       document.getElementById('body').onload = function() {
       console.log('Document loaded')
       var menu = localStorage.getItem('menu')
       if (menu === 'opened') 
         document.getElementById('navigation').classList.add('opened')
       }
      document.getElementById('menu-button').onclick = function() {
      // localstorage used to define global variable
      var menu = localStorage.getItem('menu')
      localStorage.setItem('menu', menu === 'closed' ? 'opened' : 'closed')
      document.getElementById('navigation').classList.toggle('opened')
      }
      // Window.onLoad = onLoad // global variable in js
    

    The index.js was used to import other files and it was like this:

       import _ from 'lodash'
       require('../index.njk')
       require('../base.html')
       require('../style.css')
    

    This is the Json file:

       {
       "name": "menu_moon",
       "version": "1.0.0",
       "description": "",
       "private": true,
       "dependencies": {
       "browser-sync": "^2.26.7",
       "extract-text-webpack-plugin": "^3.0.2",
       "fast-glob": "^3.1.1",
       "fs-extra": "^8.1.0",
       "g": "^2.0.1",
       "html-loader": "^0.5.5",
       "i": "^0.3.6",
       "lodash": "^4.17.15",
       "mkdirp": "^0.5.1",
       "nunjucks": "^3.2.0",
       "nunjucks-html-loader": "^1.1.0",
       "nunjucks-isomorphic-loader": "^2.0.2",
       "nunjucks-loader": "^3.0.0",
       "raw-loader": "^4.0.0"
    },
       "devDependencies": {
          "browser-sync-webpack-plugin": "^2.2.2",
          "clean-webpack-plugin": "^3.0.0",
          "copy-webpack-plugin": "^5.0.5",
          "css-loader": "^3.2.1",
          "file-loader": "^5.0.2",
          "html-webpack-plugin": "^3.2.0",
          "node-sass": "^4.13.0",
          "nunjucks-webpack-plugin": "^5.0.0",
          "sass-loader": "^8.0.0",
          "script-loader": "^0.7.2",
          "style-loader": "^1.0.1",
          "uglifyjs-webpack-plugin": "^2.2.0",
          "webpack": "^4.41.2",
          "webpack-cli": "^3.3.10",
          "webpack-dev-server": "^3.9.0"
           },
        "scripts": {
          "moon-start": "browser-sync start --server --files './**/*.*'",
          "moon-build": "node build_product_moon.js",
          "start": "webpack-dev-server --open",
          "build": "webpack"
          },
        "author": "",
        "license": "ISC"
        }
    

    I hope it was useful for others.