Sylius custom theme development – Setting up workflow powered with webpack and Symfony 4 best practices

Sylius custom theme development – Setting up workflow powered with webpack and Symfony 4 best practices

Hi everyone, in my first-ever article, I’ll show you how to setup your custom theme workflow in the latest Sylius release (1.3.0), powered with webpack and with latest Symfony 4 standards. If you haven’t read Stanislav’s articles about Sylius frontend overview and setting up a custom theme, go check it out so you can understand this part completely. 🙂

Starting with Symfony 4, web folder isnt public anymore. Only public folder is a public folder. Because of that, Symfony 4 best practices offers you Webpack Encore to use for managing assets.

Webpack Encore is a simpler way to integrate Webpack into your application. It wraps Webpack, giving you a clean & powerful API for bundling JavaScript modules, pre-processing CSS & JS, and compiling and minifying assets.

Personally, I think that Webpack Encore is cool and you get a lot out of out-of-the-box features to use. But if you want to know how things work under the hood, or you want to control your build process, then you need to make your own webpack workflow for managing assets.

For a purpose of this article, my custom theme is called inchoo-rwd.

Inside inchoo-rwd theme, create frontend folder. Inside frontend, create webpack.config.js, and package.json files.

If you don’t want to waste time configuring webpack, you can copy my setup configuration. 🙂

Webpack configuration

package.json

{
  "name": "Brca sylius config",
  "version": "1.0.0",
  "description": "sylius nanananananana",
  "main": "app.js",
  "scripts": {
    "build": "webpack --mode development",
    "dist": "webpack --mode production",
    "watch": "webpack --watch --mode development"
  },
  "author": "Brca (%lukaomi)",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "6.26.3",
    "babel-loader": "7.1.4",
    "babel-preset-env": "1.7.0",
    "browser-sync-webpack-plugin": "2.2.2",
    "copy-webpack-plugin": "4.5.4",
    "css-loader": "0.28.11",
    "mini-css-extract-plugin": "0.4.0",
    "node-sass": "4.9.0",
    "optimize-css-assets-webpack-plugin": "4.0.2",
    "sass-loader": "7.0.1",
    "uglifyjs-webpack-plugin": "1.2.5",
    "webpack": "4.10.2",
    "webpack-cli": "2.1.4",
    "webpack-dev-server": "3.1.4"
  },
  "dependencies": {
    "browser-sync": "2.24.4",
    "imagemin-webpack-plugin": "2.3.0"
  }
}

webpack.config.js

const path = require('path');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ImageminPlugin = require('imagemin-webpack-plugin').default;
 
module.exports = {
 
  entry: ['./src/js/app.js', './src/sass/style.scss'],
  output: {
    filename: './../../../public/assets/shop/js/themes/inchoo-rwd/js/app-custom.js',
    path: path.resolve(__dirname)
  },
  module: {
    rules: [
      // perform js babelization on all .js files
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
        }
      },
      // compile all .scss files to plain old css
      {
        test: /\.(sass|scss)$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
      }
    ]
  },
  plugins: [
 
    // Enable copy img theme files
    new CopyWebpackPlugin(
      [
        {
          from: './src/images/',
          to: './../../../public/assets/shop/images/themes/inchoo-rwd/images/',
        },
      ]),
 
    // Enable img optimization
    new ImageminPlugin ({
      test: /\.(jpe?g|png|gif|svg)$/i,
      pngquant: {
        quality: '95-100'
      }
    }),
 
    // extract css into dedicated file
    new MiniCssExtractPlugin({
      filename: './../../../public/assets/shop/css/themes/inchoo-rwd/css/style.css',
    }),
 
    // Watch for changes
    new BrowserSyncPlugin({
      host: 'localhost',
      port: '8080',
      // If using local domain for project change this.
      proxy: 'http://sylius.loc', // ---> change this url for yours
      open: false,
      files: [{
        match: ['./../**/**/*.html.twig'],
        fn: function (event, file) {
          if (event === "change") {
            const bs = require('browser-sync').get('bs-webpack-plugin');
            bs.reload();
          }
        }
      },
        {
          match: ['./src/js/app.js', './src/sass/style.scss'],
          fn: function (event, file) {
            if (event === "change") {
              const bs = require('browser-sync').get('bs-webpack-plugin');
              bs.stream();
            }
          }
        }],
      injectChanges: true,
      notify: true
    })
  ],
 
  optimization: {
    minimizer: [
      // enable the js minification plugin
      new UglifyJSPlugin({
        cache: true,
        parallel: true
      }),
      // enable the css minification plugin
      new OptimizeCSSAssetsPlugin({})
    ]
  }
};

I wouldn’t go into details line by line what’s inside this configuration files, but generaly in this example, features that you can use are:

  • Babel polyfill for writing ES6 javascript
  • SASS, CSS and JS optimization
  • Browsersync
  • Image optimizations

If you like, you can configure it to use PostCSS or do other crazy webpack stuff. 🙂

Setting up workflow

Next, go inside terminal directory sylius-project/themes/inchoo-rwd/frontend, and hit:

npm install

After you install following dependencies, inside frontend folder create src and put files and folders like in the picture bellow.

Sylius custom theme folder configuration

Inside app.js and style.scss, add a folowing code:

app.js

import './../sass/style.scss';
 
class app {
  helloWorld() {
    alert('wohooo ES6 ready !!!!');
  }
}
 
const a = new app();
a.helloWorld();

Because we use css-loader to have css-in-js feature, we need to import main sass file inside app.js to be rendered. In this workflow, app.js represents our main file where you include all your components and vendors.

styles.scss

$primary: #56db59;
 
body {
    background: $primary;
    font-size: 24px;
}

Great! Now you configured your basic workflow powered with webpack.

Go inside your theme SyliusShopBundle/views/layout.twig.html and add folowing code:

At line 21, replace

{% include '@SyliusUi/_stylesheets.html.twig' with {'path': 'assets/shop/css/style.css'} %}

with

{% include '@SyliusUi/_stylesheets.html.twig' with {'path': 'assets/shop/css/themes/inchoo-rwd/css/style.css'} %}

And at line 76

{% include '@SyliusUi/_javascripts.html.twig' with {'path': 'assets/shop/js/app.js'} %}

add below

{% include '@SyliusUi/_javascripts.html.twig' with {'path': 'assets/shop/js/themes/inchoo-rwd/js/app-custom.js'} %}

If you got lost, you can download files from github repo. 🙂

To be upgrade-proof, my advice is not to remove Sylius vendor app.js (Sylius render core logic through it), while trying to grab parts from Sylius vendor js, and join it up with your custom js logic into one single js file. When updates come, and if something changes, you will need to check changelogs to fix what went wrong. 🙂

In current frontend workflow, you have three options for webpack build process (you can look inside package.json)

  1. Development – in console: npm run build
  2. Development+watch – in console: npm run watch
  3. Production – in console: npm run production

In the same terminal directory, hit following command:

npm run build

That command will run folowing script to start webpack build task process. If you complete all previous steps, you should see new files and folders inside public folder.

Sylius custom theme workflow folder and files structure

Refresh the browser. You should see the changes.

Sylius custom theme complete all steps

Woohoo! 🙂 you made it to the end. Here is a last final tip for ya 🙂

Because of Sylius’ core, app.js that we use in layout.twig.html we can use libaries that Sylius use like:

  • jquery”: “^3.2.0”
  • lightbox2″: “^2.9.0”
  • semantic-ui-css”: “^2.2.0”

and others…

So you dont need to include them again if you need them.

To test it out inside our theme app.js file, insert the following code:

$(document).ready(function(){
  alert('oldschool Ready !!!');
});

In the same terminal directory, hit following command:

npm run build

Refresh the browser.

Sylius complete all steps with jquery

And that’s it! 🙂

Conclusion

Hope I helped you to quickly and easily understand the process of creating custom theme workflow on Sylius 1.3.0 version based on Symfony 4 best practices. I want to emphasize that currently, there isn’t a standard way for creating custom theme, and this is my interpretation of doing it, based on my previous experience working with Sylius. My advice to you guys is to regularly check changelogs to see what is going on with current development, so you can be up to date with it for future updates! 🙂

Related Inchoo Services

You made it all the way down here so you must have enjoyed this post! You may also like:

Sylius custom theme development – Create a theme Stanislav Mihic
Stanislav Mihic, | 0

Sylius custom theme development – Create a theme

Sylius custom theme development – initial setup Stanislav Mihic
Stanislav Mihic, | 0

Sylius custom theme development – initial setup

Creating Sylius Fixtures Toni Pap
Toni Pap, | 0

Creating Sylius Fixtures

3 comments

  1. Hey,

    Great article stuff for setup your custom theme workflow in the latest Sylius release (1.3.0). It really awesome information here. I really enjoy the nice article.

    thanks for sharing great information!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <s> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.

Tell us about your project

Drop us a line. We'd love to know more about your project.