Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack dev server watches Twig

I'm using Symfony 4 with Symfony Encore to handle assets, and some useful features, such as HMR.

Currently, I can handle Sass files, CSS files, JS, etc, and it works fine with HMR.

Now I would like to be able to make Weback dev server watch *.twig files for changes and trigger a live reload (as hot reload wouldn't be an option for server-side rendered templates).

I've seen things about --watchContentBase and contentBase options, but it doesn't do anything in my case:

WDS CLI :

./node_modules/.bin/encore dev-server --hot --disable-host-check --watchContentBase --contentBase ./templates/ --reload

webpack.config.js :

const Encore = require('@symfony/webpack-encore');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

Encore
    .setOutputPath('public/build/')
    .setPublicPath('/build')
    .cleanupOutputBeforeBuild()
    .autoProvidejQuery()  
    .addPlugin(new MiniCssExtractPlugin('[name].css'))
    .enableSourceMaps(!Encore.isProduction())
    .addLoader({
        test: /\.(sc|sa|c)ss$/,
        use: ['css-hot-loader'].concat(
            MiniCssExtractPlugin.loader,
            {
                loader: 'css-loader'
            },
            {
                loader: 'postcss-loader'
            },
            // {
            //     loader: 'postcss-loader'
            // },
            {
                loader: 'sass-loader'
            }            
        ),
      },)
      .addLoader({
        test: /\.twig$/,
        loader: 'raw-loader'
      },)
    .enableVersioning(Encore.isProduction())
    .addEntry('autocall-main', './assets/js/index.js')
    // .addStyleEntry('autocall-main', ['./assets/scss/index.scss'])
    .splitEntryChunks()
    .enableSingleRuntimeChunk()
;
const config = Encore.getWebpackConfig();

module.exports = config;

My project files / folders follows the classic Symfony 4 structure: https://github.com/symfony/demo

What do I miss there?

like image 948
enguerranws Avatar asked Jan 15 '19 09:01

enguerranws


1 Answers

Today, the year 2020, i have two solutions:

Webpack config solution

As you had said: I've seen things about --watchContentBase and contentBase options..., this has nothing to do with encore. Its a default webpack configurations and you can learn more from webpack doc here

According to Advanced Webpack Config docs here you can extend webpack configs by calling var config = Encore.getWebpackConfig();

I have implemented as shown in the code below. For my case its working fine.

// webpack.config.js
var Encore = require('@symfony/webpack-encore');
var path = require('path');

// Manually configure the runtime environment if not already configured yet by the "encore" command.
// It's useful when you use tools that rely on webpack.config.js file.
if (!Encore.isRuntimeEnvironmentConfigured()) {
    Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}

Encore
    // directory where compiled assets will be stored
    .setOutputPath('public/build/')
    .setPublicPath('/build')
    .addEntry('global', './assets/app.js')

    // ... Your other encore code


    // EXTEND/OVERRIDE THE WEBPACK CONFIG

    const fullConfig = Encore.getWebpackConfig();
    fullConfig.name = 'full';

    // watch options poll is used to reload the site after specific set time
    // polling is useful when running Encore inside a Virtual Machine
    // more: https://webpack.js.org/configuration/watch/
    fullConfig.watchOptions = {
        poll: true,
        ignored: /node_modules/
    };

    fullConfig.devServer = {
        public: 'http://localhost:3000',
        allowedHosts: ['0.0.0.0'],
        // extend folder to watch in a symfony project
        // use of content base
        // customize the paths below as per your needs, for this simple 
        //example i will leave them as they are for now.
        contentBase: [
            path.join(__dirname, 'templates/'), // watch twig templates folder
            path.join(__dirname, 'src/') // watch the src php folder
        ],
        // enable watching them
        watchContentBase: true,
        compress: true,
        open: true,
        disableHostCheck: true,
        progress: true,
        watchOptions: {
            watch: true,
            poll: true
        }
    };


// export it
module.exports = fullConfig;

Another solution

If you need a simple implementation you can use: webpack-watch-files-plugin. I prefer this, by the time you are reading this answer it might be abandoned but there many others with same functionality. In Symfony docs here you can implement Custom Loaders & Plugins as below. Using the above mentioned plugin we can implent it as follow:

// webpack.config.js
const WatchExternalFilesPlugin = require('webpack-watch-files-plugin').default;

Encore
    // ...your code

     .addPlugin(new WatchExternalFilesPlugin({
            files: [
                '/templates', // watch files in templates folder
                '/src', // watch files in src folder
                '!../var', // don't watch files in var folder (exclude)
            ],
            verbose: true
        }))

    //...your code
;

Cheers. Happy coding!

like image 173
Ngatia Frankline Avatar answered Sep 30 '22 08:09

Ngatia Frankline