Sage 9 browsersync not updating right

@strarsis - thanks so much for this.

Should browsersync work with webpack 4 to reload blade file changes?
That’s the only thing left that I can’t get to work.

I may attempt to upgrade to webpack 5 soon otherwise.

I just tested it with webpack4 branch - and webpack watch/BrowserSync works fine.

1 Like

I attempted to switch to webpack 5, got a bunch of errors on build.
Switched back to webpack 4, getting errors as well, including this one:

Preformatted textError: Cannot find module 'extract-text-webpack-plugin'

I added that yarn add extract-text-webpack-plugin

and then build again and I receive this:

 ERROR  Failed to compile with 1 errors                                            2:41:49 PM

This relative module was not found:

* ./styles/main.scss in multi ./scripts/main.js ./styles/main.scss
Built at: 01/12/2021 2:41:49 PM
                    Asset      Size      Chunks                   Chunk Names
    scripts/customizer.js  4.82 KiB  customizer  [emitted]        customizer
scripts/customizer.js.map  3.99 KiB  customizer  [emitted] [dev]  customizer
          scripts/main.js  10.7 KiB        main  [emitted]        main
      scripts/main.js.map  9.45 KiB        main  [emitted] [dev]  main
Entrypoint main = scripts/main.js scripts/main.js.map
Entrypoint customizer = scripts/customizer.js scripts/customizer.js.map
error Command failed with exit code 2.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

after yarn start

 ERROR  Failed to compile with 1 errors                                           3:08:02 PM

This relative module was not found:

* ./styles/main.scss in multi ./resources/assets/build/util/../helpers/hmr-client.js ./scripts/main.js ./styles/main.scss
[Browsersync] Proxying: https://trellis.project.build
[Browsersync] Access URLs:
 --------------------------------------
       Local: https://localhost:3000
    External: https://192.168.0.58:3000
 --------------------------------------
          UI: http://localhost:3001
 UI External: http://localhost:3001
 --------------------------------------
[Browsersync] Watching files...
[Browsersync] Reloading Browsers...
[Browsersync] Reloading Browsers...
[Browsersync] Reloading Browsers... 

The good news is that browsersync is watching my blade files now. That’s a relief after a few years without it!
Attempting to determine what is now causing this issue and then I should be set free!

It seems that something wasn’t merged from the webpack5 PR into your existing webpack.config.js,
as with recent webpack, a different extractor should be used:

Merge the webpack.config.js and the other config files, as they contain slight modifications. This wouldn’t be noticeable when starting from scratch, but when reusing an existing webpack.config.js some parts may be overlooked.

Turns out it was the webpack preset file creating the problem.
Building and watching works great now but it appears the styles are not working at all.

I’m updating a project with tailwind 2 which was created using this:

additionally, this browsersync is constantly reloading on it’s own

Furthermore, styles are being compiled and do work:

https://trellis.project.build/app/themes/sage/dist/styles/main.css

However, none of the Tailwind classes are working. These were working before the patches were made.

I don’t know enough about all of this but it appears that perhaps webkit.config.preset.js is required for Tailwind?

I’ve put this file back in place and when I attempt to build, I get errors:

[webpack-cli] Error: Cannot find module 'extract-text-webpack-plugin'

Updated-
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const ExtractTextPlugin = require('mini-css-extract-plugin');

Build and get this error:
[webpack-cli] Error: Cannot find module 'tailwindcss'

Checked my package.json and Tailwind is missing so I added it back, updated and built again:

[webpack-cli] Failed to load '/Users/joshb/Documents/_development/_trellis/trellis.project.build/site/web/app/themes/sage/resources/assets/build/webpack.config.js'
[webpack-cli] TypeError: ExtractTextPlugin.extract is not a function

Not sure where to go from here :frowning:

Here’s the file. Really appreciate any help.

webpack.config.preset.js
'use strict'; // eslint-disable-line

const ExtractTextPlugin = require('extract-text-webpack-plugin');

const config = require('./config');

/** Default PostCSS plugins */
let postcssPlugins = [
  require('tailwindcss')(`${config.paths.assets}/styles/tailwind.config.js`),
  require('autoprefixer')(),
];

/** Add cssnano when optimizing */
config.enabled.optimize
  ? postcssPlugins.push(
      require('cssnano')({
        preset: ['default', { discardComments: { removeAll: true } }],
      })
    )
  : false;

module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        include: config.paths.assets,
        use: ExtractTextPlugin.extract({
          fallback: 'style',
          use: [
            { loader: 'cache' },
            { loader: 'css', options: { sourceMap: false } },
            {
              loader: 'postcss',
              options: {
                postcssOptions: {
                  parser: config.enabled.optimize
                  ? 'postcss-safe-parser'
                  : undefined,
                  plugins: postcssPlugins,
                  sourceMap: false,
                }
              },
            },
            {
              loader: 'resolve-url',
              options: { silent: true, sourceMap: false },
            },
            {
              loader: 'sass',
              options: { sourceComments: true, sourceMap: false },
            },
          ],
        }),
      },
    ],
  },
};

Not only that line has to be replaced but also where the new extractor is used:

I recommend that you merge the webpack.config.js using a merge tool (e.g. WinMerge).
Or post it here if you have problems with merging the changes so I can try it.

My webpack.config.js file is correct, it’s the webpack.config.preset.js file that is creating issues. If I rename/remove the preset file, everything compiles fine but tailwind is not being installed correctly. Once I have the preset file in place I get errors when compiling.

'use strict'; // eslint-disable-line

const ExtractTextPlugin = require('extract-text-webpack-plugin');

const config = require('./config');

/** Default PostCSS plugins */
let postcssPlugins = [
  require('tailwindcss')(`${config.paths.assets}/styles/tailwind.config.js`),
  require('autoprefixer')(),
];

/** Add cssnano when optimizing */
config.enabled.optimize
  ? postcssPlugins.push(
      require('cssnano')({
        preset: ['default', { discardComments: { removeAll: true } }],
      })
    )
  : false;

module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        include: config.paths.assets,
        use: ExtractTextPlugin.extract({
          fallback: 'style',
          use: [
            { loader: 'cache' },
            { loader: 'css', options: { sourceMap: false } },
            {
              loader: 'postcss',
              options: {
                postcssOptions: {
                  parser: config.enabled.optimize
                  ? 'postcss-safe-parser'
                  : undefined,
                  plugins: postcssPlugins,
                  sourceMap: false,
                }
              },
            },
            {
              loader: 'resolve-url',
              options: { silent: true, sourceMap: false },
            },
            {
              loader: 'sass',
              options: { sourceComments: true, sourceMap: false },
            },
          ],
        }),
      },
    ],
  },
};

You are right. Apparently the webpack5 PR only changes the base files, but not what is additionally added on top of these (composer create-project roots/sage selection). Hence I would have to create a PR for these additional config, as for Tailwind, Bootstrap, etc.

Adjust the merging at the very end of the base webpack.config.js:

// [...]

/**
 * During installation via sage-installer (i.e. composer create-project) some
 * presets may generate a preset specific config (webpack.config.preset.js) to
 * override some of the default options set here. We use webpack-merge to merge
 * them in. If you need to modify Sage's default webpack config, we recommend
 * that you modify this file directly, instead of creating your own preset
 * file, as there are limitations to using webpack-merge which can hinder your
 * ability to change certain options.
 */

module.exports = mergeWithRules({
  module: {
    rules: {
	  test: 'match',
	  use: {
	    loader: 'match',
	    options: 'replace',
	  },
    },
  },
})( webpackConfig, desire(`${__dirname}/webpack.config.preset`) ? desire(`${__dirname}/webpack.config.preset`) : {} )

Then use this updated tailwind variant of webpack.config.preset.js;

'use strict'; // eslint-disable-line

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

const config = require('./config');

module.exports = {
  module: {
    rules: [
	  {
        test: /\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          { loader: 'css-loader', options: { sourceMap: config.enabled.sourceMaps } },
          {
            loader: 'postcss-loader', options: {
              postcssOptions: {
                config: path.join( __dirname, 'postcss.config.tailwind.js' ), // PostCSS tailwind specific config
                ctx: config,
              },
              sourceMap: config.enabled.sourceMaps,
            },
          },
          { loader: 'resolve-url-loader', options: { sourceMap: config.enabled.sourceMaps } },
          {
            loader: 'sass-loader', options: {
              sassOptions: {
                sourceComments: true,
              },
              sourceMap: true, //config.enabled.sourceMaps, // false causes a resolve issue
            },
          },
        ],
      },
    ],
  },
};

The PostCSS loader expects a config file, hence the tailwind-tailored PostCSS config file postcss.config.tailwind.js has to be added:

/* eslint-disable */

module.exports = (api) => {

  const cssnanoConfig = {
    preset: ['default', { discardComments: { removeAll: true } }]
  };

  return {
    parser: api.options.ctx.enabled.optimize ? 'postcss-safe-parser' : undefined,
    plugins: {
      tailwindcss: `${api.options.ctx.paths.assets}/styles/tailwind.config.js`,
      autoprefixer: true,
      cssnano: api.options.ctx.enabled.optimize ? cssnanoConfig : false,
    },
  };

};

After making the changes you provided, I am now receiving this error on build:

Error: Cannot find module 'path-exists'

Full output:

yarn run v1.22.10
$ webpack --progress --config resources/assets/build/webpack.config.js
internal/modules/cjs/loader.js:818
  throw err;
  ^

Error: Cannot find module 'path-exists'
Require stack:
- /Users/joshb/Documents/_development/_trellis/_project/trellis.project.build/site/web/app/themes/project/node_modules/find-up/index.js
- /Users/joshb/Documents/_development/_trellis/_project/trellis.project.build/site/web/app/themes/project/node_modules/import-local/node_modules/pkg-dir/index.js
- /Users/joshb/Documents/_development/_trellis/_project/trellis.project.build/site/web/app/themes/project/node_modules/import-local/index.js
- /Users/joshb/Documents/_development/_trellis/_project/trellis.project.build/site/web/app/themes/project/node_modules/webpack-cli/bin/cli.js
- /Users/joshb/Documents/_development/_trellis/_project/trellis.project.build/site/web/app/themes/project/node_modules/webpack/bin/webpack.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:815:15)
    at Function.Module._load (internal/modules/cjs/loader.js:667:27)
    at Module.require (internal/modules/cjs/loader.js:887:19)
    at require (/Users/joshb/Documents/_development/_trellis/_project/trellis.project.build/site/web/app/themes/project/node_modules/v8-compile-cache/v8-compile-cache.js:159:20)
    at Object.<anonymous> (/Users/joshb/Documents/_development/_trellis/_project/trellis.project.build/site/web/app/themes/project/node_modules/find-up/index.js:4:20)
    at Module._compile (/Users/joshb/Documents/_development/_trellis/_project/trellis.project.build/site/web/app/themes/project/node_modules/v8-compile-cache/v8-compile-cache.js:192:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Module.require (internal/modules/cjs/loader.js:887:19) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/Users/joshb/Documents/_development/_trellis/_project/trellis.project.build/site/web/app/themes/project/node_modules/find-up/index.js',
    '/Users/joshb/Documents/_development/_trellis/_project/trellis.project.build/site/web/app/themes/project/node_modules/import-local/node_modules/pkg-dir/index.js',
    '/Users/joshb/Documents/_development/_trellis/_project/trellis.project.build/site/web/app/themes/project/node_modules/import-local/index.js',
    '/Users/joshb/Documents/_development/_trellis/_project/trellis.project.build/site/web/app/themes/project/node_modules/webpack-cli/bin/cli.js',
    '/Users/joshb/Documents/_development/_trellis/_project/trellis.project.build/site/web/app/themes/project/node_modules/webpack/bin/webpack.js'
  ]
}
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

I checked out the webpack5 branch and then put a modified tailwind configuration on top of it.
You can try the tested sage 9 + webpack 5 + tailwind configuration from this repository:


Together with latest Tailwind, the dependencies require node v12 or higher, you can use a known working node version (LTS at time of writing) by invoking nvm use v14.15.3. To ensure the same node version is used among the whole team, you can create a .nvmrc with the node version as content.
I also had to modify some styles for making them compatible with latest Tailwind (new rules introduced).

@strarsis - thanks for all of that… I literally just put together my own working repo here:

Everything works fine on mine.

I just tried yours and on yarn watch it returns this error:

[webpack-cli] ReferenceError: merge is not defined

I updated the theme installation instructions as well.

Theme installation
Clone this repo and update the publicPath and devUrl in config.json

# @ resources/assets/config.json
{
  "entry": {
    "main": [
      "./scripts/main.js",
      "./styles/main.scss"
    ],
    "customizer": [
      "./scripts/customizer.js"
    ]
  },
  "publicPath": "/app/themes/sage9-wp5-tailwind2",
  "devUrl": "http://sage9-wp5-tailwind2.test",
  "proxyUrl": "http://localhost:3000",
  "cacheBusting": "[name]_[hash:8]",
  "watch": [
    "app/**/*.php",
    "config/**/*.php",
    "resources/views/**/*.php"
  ]
}
Be sure you're running node 12 first.

Navigate to your theme directory and run:

yarn && yarn build
Still in your theme, run:

composer install
Optionally update your theme details

# @ resources/style.css
/*
Theme Name:         Sage Starter Theme
Theme URI:          https://roots.io/sage/
Description:        Sage is a WordPress starter theme.
Version:            9.0.10
Author:             Roots
Author URI:         https://roots.io/
Text Domain:        sage

License:            MIT License
License URI:        http://opensource.org/licenses/MIT
*/
Now go activate theme.

@joshb: The old merge method was used for production builds and watch.
I pushed a fix commit, it should work now.

1 Like

@strarsis - I just installed a new theme and can confirm that your repo works as well.

There appears to be an issue yet with browsersync. Is it normal behavior for browsersync to constantly be reloading the browser itself? This doesn’t happen on my sage/wp/tailwind repo I created but it does on yours.

[Browsersync] Access URLs:
 --------------------------------------
       Local: https://localhost:5552
    External: https://192.168.0.58:5552
 --------------------------------------
          UI: http://localhost:3001
 UI External: http://localhost:3001
 --------------------------------------
[Browsersync] Watching files...
[Browsersync] Reloading Browsers...
[Browsersync] Reloading Browsers... (buffered 3 events)
[Browsersync] Reloading Browsers... (buffered 14 events)
[Browsersync] Reloading Browsers... (buffered 7 events)
[Browsersync] Reloading Browsers... (buffered 61 events)
[Browsersync] Reloading Browsers... (buffered 77 events)
[Browsersync] Reloading Browsers... (buffered 72 events)
[Browsersync] Reloading Browsers... (buffered 259 events)
[Browsersync] Reloading Browsers... (buffered 16 events)
[Browsersync] Reloading Browsers... (buffered 5 events)
[Browsersync] Reloading Browsers... (buffered 5 events)
[Browsersync] Reloading Browsers... (buffered 5 events)
[Browsersync] Reloading Browsers... (buffered 37 events) 

Additionally, browsersync doesn’t appear to be updating when adding new html tags, etc.
I have to hard refresh a 2 to 5 times to see the update. OR I have to build again and then refresh.

But if I add a tailwind class to a tag for example, then browsersync updates immediately.

After further use, it appears the reloading browsers is happening with my repo as well.
It reloads almost every second or two.

Makes it impossible to user the inspector.

Hm, I am unable to reproduce this issue though… E.g. when I clone the repository, configure + start a test WordPress container, install the dependencies and start watching (nvm use lts/*; nvm install; composer install; npm start), wait for the page to open and then change something, e.g. add body { background: red; } to _page.scss, the page, the page turns red. When I change it something else, e.g. body { background: blue; } the page turns blue. I don’t experience a BrowserSync reload loop.

  • Are you using HTTPS on the test server or on BrowserSync itself?
  • Are you using the Chrome browser?
  • What do you see in Developer JavaScript console, any errors/warnings, CORS errors from BrowserSync?

I am using a self signed certificate with trellis cert which is also not secure with localhost.

I am using chrome.

I dont believe I have any console errors but will confirm once I get back to my workstation