Home > Net >  How to setup live reloading and assets compiling with Webpack in a Drupal project?
How to setup live reloading and assets compiling with Webpack in a Drupal project?

Time:06-05

So far I was able to setup Webpack to compile Sass and JavaScript. I compile a styles.scss and a index.js laying respectively in assets/scss/ and assets/js/ folder in my Drupal custom theme called amazon.

I generate a styles.css and a index.js in assets/dist/ folder. And those are included in my Twig templates with amazon.libraries.yml.

Is there a way to have live reloading as well? As for now my assets get recompiled after each changes but I have to reload the browser manually. I'm using Drupal v8.9.20 and Node.js v16.15.0.

assets/js/index.js:

import "../scss/styles.scss";
console.log("Hello World");

package.json:

{
  "name": "amazon",
  "scripts": {
    "start": "webpack",
    "build": "MODE=production webpack"
  },
  "devDependencies": {
    "@babel/core": "^7.14.6",
    "@babel/preset-env": "^7.14.7",
    "autoprefixer": "^10.4.7",
    "babel-loader": "^8.2.2",
    "css-loader": "^6.0.0",
    "css-minimizer-webpack-plugin": "^3.0.2",
    "mini-css-extract-plugin": "^2.1.0",
    "postcss-loader": "^6.1.1",
    "postcss-preset-env": "^7.6.0",
    "sass": "^1.52.1",
    "sass-loader": "^12.1.0",
    "webpack": "^5.49.0",
    "webpack-cli": "^4.9.1"
  }
}

webpack.config.js:

const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const target = process.env.MODE === "production" ? "browserslist" : "web";
const mode = process.env.MODE === "production" ? "production" : "development";
module.exports = {
  entry: "./assets/js/index.js",
  output: {
    path: path.resolve(__dirname, "assets/dist"),
    filename: "index.js",
  },
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          MiniCssExtractPlugin.loader,

          {
            loader: "css-loader",
            options: {
              url: false,
            },
          },
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [["postcss-preset-env"]],
              },
            },
          },
          {
            loader: "sass-loader",
            options: {
              implementation: require("sass"),
            },
          },
        ],
      },

      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
          },
        },
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "styles.css",
    }),
  ],
  optimization: {
    minimizer: ["...", new CssMinimizerPlugin()],
  },
  target: target,
  devtool: mode == "production" ? false : "source-map",
  mode: mode,
  watch: mode !== "production",
};

.browserslistrc:

defaults

CodePudding user response:

I could setup live reloading using BrowserSync. I'm proxying BrowserSync url (localhost:3000) with my Drupal development url (amazon.test).

The setup from the question is a good start, change package.json and webpack.config.js as below, run npm i, then npm start.

package.json:

{
  "name": "amazon",
  "scripts": {
    "start": "webpack",
    "build": "MODE=production webpack"
  },
  "devDependencies": {
    "@babel/core": "^7.14.6",
    "@babel/preset-env": "^7.14.7",
    "autoprefixer": "^10.4.7",
    "babel-loader": "^8.2.2",
    "browser-sync": "^2.27.10",
    "browser-sync-webpack-plugin": "^2.3.0",
    "css-loader": "^6.0.0",
    "css-minimizer-webpack-plugin": "^3.0.2",
    "mini-css-extract-plugin": "^2.1.0",
    "postcss-loader": "^6.1.1",
    "postcss-preset-env": "^7.6.0",
    "sass": "^1.52.1",
    "sass-loader": "^12.1.0",
    "webpack": "^5.49.0",
    "webpack-cli": "^4.9.1"
  }
}

webpack.config.js:

const path = require("path");
const BrowserSyncPlugin = require("browser-sync-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const target = process.env.MODE === "production" ? "browserslist" : "web";
const mode = process.env.MODE === "production" ? "production" : "development";
module.exports = {
  mode,
  watch: mode !== "production",
  entry: "./assets/js/index.js",
  output: {
    path: path.resolve(__dirname, "assets/dist"),
    filename: "index.js",
  },
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          MiniCssExtractPlugin.loader,

          {
            loader: "css-loader",
            options: {
              url: false,
            },
          },
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [["postcss-preset-env"]],
              },
            },
          },
          {
            loader: "sass-loader",
            options: {
              implementation: require("sass"),
            },
          },
        ],
      },

      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
          },
        },
      },
    ],
  },
  plugins: [
    new BrowserSyncPlugin(
      // BrowserSync options
      {
        // browse to http://localhost:3000/ during development
        host: "localhost",
        port: 3000,
        proxy: "amazon.test", // change to your own development url
        files: [
          {
            match: ["**/*.php"],
          },
          {
            match: ["templates/*.twig"],
          },
          {
            match: ["**/*.js"],
          },
          {
            match: ["**/*.scss"],
          },
          {
            match: ["**/*.png"],
          },
          {
            match: ["**/*.jpeg"],
          },
          {
            match: ["**/*.jpg"],
          },
          {
            match: ["**/*.svg"],
          },
        ],
        notify: false,
      },
      // plugin options
      {
        reload: true,
      }
    ),
    new MiniCssExtractPlugin({
      filename: "styles.css",
    }),
  ],
  optimization: {
    minimizer: ["...", new CssMinimizerPlugin()],
  },
  target: target,
  devtool: mode == "production" ? false : "source-map",
};

  • Related