Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

JavaScript for PHP Geeks: Webpack for Module Loading Awesomeness

3:43:03

What you'll be learning

This tutorial explains the concepts of an old version of Webpack using an old version of Symfony. The most important concepts are still the same, but you should expect significant differences in new versions.
// composer.json
{
    "require": {
        "php": "^7.2.0",
        "symfony/symfony": "3.3.*", // v3.3.16
        "twig/twig": "2.10.*", // v2.10.0
        "doctrine/orm": "^2.5", // v2.7.0
        "doctrine/doctrine-bundle": "^1.6", // 1.10.3
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.5
        "symfony/swiftmailer-bundle": "^2.3", // v2.6.3
        "symfony/monolog-bundle": "^2.8", // v2.12.1
        "symfony/polyfill-apcu": "^1.0", // v1.4.0
        "sensio/distribution-bundle": "^5.0", // v5.0.22
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.26
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "friendsofsymfony/user-bundle": "^2.0", // v2.1.2
        "doctrine/doctrine-fixtures-bundle": "~2.3", // v2.4.1
        "doctrine/doctrine-migrations-bundle": "^1.2", // v1.3.2
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "friendsofsymfony/jsrouting-bundle": "^1.6" // 1.6.0
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.1.6
        "symfony/phpunit-bridge": "^3.0" // v3.3.5
    }
}
// package.json
{
    "dependencies": [],
    "devDependencies": {
        "babel-core": "^6.25.0", // 6.25.0
        "babel-loader": "^7.1.1", // 7.1.1
        "babel-plugin-syntax-dynamic-import": "^6.18.0", // 6.18.0
        "babel-preset-env": "^1.6.0", // 1.6.0
        "bootstrap-sass": "^3.3.7", // 3.3.7
        "clean-webpack-plugin": "^0.1.16", // 0.1.16
        "copy-webpack-plugin": "^4.0.1", // 4.0.1
        "core-js": "^2.4.1", // 2.4.1
        "css-loader": "^0.28.4", // 0.28.4
        "extract-text-webpack-plugin": "^3.0.0", // 3.0.0
        "file-loader": "^0.11.2", // 0.11.2
        "font-awesome": "^4.7.0", // 4.7.0
        "jquery": "^3.2.1", // 3.2.1
        "lodash": "^4.17.4", // 4.17.4
        "node-sass": "^4.5.3", // 4.5.3
        "resolve-url-loader": "^2.1.0", // 2.1.0
        "sass-loader": "^6.0.6", // 6.0.6
        "style-loader": "^0.18.2", // 0.18.2
        "sweetalert2": "^6.6.6", // 6.6.6
        "webpack": "^3.4.1", // 3.4.1
        "webpack-chunk-hash": "^0.4.0", // 0.4.0
        "webpack-dev-server": "^2.6.1", // 2.6.1
        "webpack-manifest-plugin": "^1.2.1" // 1.2.1
    }
}

Tip

This tutorial covers Webpack 3 But don't worry! The vast majority of the concepts are still the same. So, if you want to learn Webpack & module loading, you're still in the right place. The biggest differences are in the CommonsChunkPlugin area.

In JavaScript, if you're still manually including each JavaScript file you depend on with a script tag... there's a better way! ES6 introduced the concept of modules: the ability (finally!) to isolate our JavaScript into small components that live in different files (like we do with classes in JavaScript).

But, to get this to work on the web, we need some help. We need something that's able to read our imports and aggregate everything we need into a single JavaScript file. We need webpack:

  • Using npm... and then yarn for package management
  • Webpack setup: package all modules into a single file
  • Calling Babel from webpack via a loader
  • Webpack dev tools for fast development
  • Webpack Hot Reloading!?
  • Handling multiple files ("entry points")
  • Using Uglify and prepping for production
  • Cache-busting with hashed filenames
  • CommonsChunkPlugin: package common modules together
  • Loading & Packaging CSS/SCSS & images form JavaScript!?

And most importantly: become empowered to (finally) write organized JavaScript!


Your Guides

Ryan Weaver Leanna Pelham

Buy Access

Join the Conversation?

31
Login or Register to join the conversation
Mike P. Avatar
Mike P. Avatar Mike P. | posted 3 years ago

Awesome tutorial, thank you! And what / do you even recommend to optimize/minify the html.twig pages as well? (Remove whitespaces and code comments(?))

If yes, what do you use?

{% apply spaceless %}?
https://github.com/voku/htm...
Or something other than that?

I can't find any information about that on your great site.

2 Reply

Hey Mike P.!

Actually, awesome question :). I'd say 2 things:

1) Use compression on your server - like - https://docs.nginx.com/ngin... - that will probably take care of... most of the issue automatically :).

2) Use tools like https://developers.google.c... to see what performance problems you have and debug those. For example, if you don't have compression enabled, it'll tell you. Once you DO, it'll tell you the next thing to worry about. My guess is that (once you're gzipping responses), removing whitespace would be a super-micro optimization.

Cheers!

1 Reply
Default user avatar

I am eagerly waiting for this tutorial to be available.

1 Reply

Hey Sks,

We're working on this tutorial, it should be released right after Ansible tutorial, see our roadmap: http://knpuniversity.com/co... . For now you can subscribe to this course with "Notify me when course is available" button.

Cheers!

Reply
Default user avatar

Thanks for the reply. and roadmap link.

Reply
Zorpen Avatar

Wheeen? ;)
Can't wait!

1 Reply

I'll start working next week on this! No release date yet :/... but I'm going to do my best! This tutorial will be fun :)

1 Reply
Zorpen Avatar

Thanks Ryan.
Can't wait for this and React Tutorial.
How long it usually takes to make tutorial like this? A day, a week, a month? :P

Reply

Good question - it's a few weeks... or a month! But, we (Symfony) will have a surprise related to webpack (in the new few weeks)...

1 Reply
Zorpen Avatar

Ah, The Webpack Encore :) Nice job! So i guess you were waiting with this tutorial till Encore was released? ;)

Reply

:) You got it! I'll start writing this tutorial quite soon (hopefully next week).

Reply
Default user avatar

I love your tutorials guys. It's nice to learn things in a fun way))) Can't wait for the next releases

Reply
JuanLuisGarciaBorrego Avatar
JuanLuisGarciaBorrego Avatar JuanLuisGarciaBorrego | posted 5 years ago

Hi Knp!
When this course begins?
Unfortunately, javascript is very imperative today for any application however small .. =(

Thanks!!!

Reply

Hey Juan,

I totally agree with you! For now, we're releasing EasyAdminBundle, then we will start working on this one, but I can't tell you any estimated release date yet. We're going to release it after Ansistrano tutorial, see our roadmap for new courses: http://knpuniversity.com/co...

Cheers!

Reply

I'm the hold up on this! But I can tell you that it i AM writing this tutorial right now... finally :).

Reply
Nicolas-S Avatar
Nicolas-S Avatar Nicolas-S | posted 5 years ago

Can't wait for this one either !!

Reply
Default user avatar
Default user avatar Babel Yaarrn | posted 5 years ago

When will this tut be availablu :D

Reply

Hey Babel!

This tutorial should be released right after Ansible tutorial, you can check our roadmap to see what's coming next http://knpuniversity.com/co...
Also you can subscribe to this mailing list, so you get notified inmediately when this course gets available.

Have a nice day!

Reply

Just to inform you that this course is live!

Reply
Default user avatar
Default user avatar J.R. Jenkins | posted 5 years ago | edited

Hey KNP Team-

I tried to take a look at the "finish" code on my Windows machine and node was very unhappy with the webpack.config.js file (although it worked on my Mac so yay for platform differences!). Just wanted to post this in case another Windows user runs into issues.

I don't have the exact error in front of me today (I am in the office), but it seemed to be a parsing error. When I ran the webpack.config.js file through eslint it complained about an unexpected token on line 178


/node_modules/.bin/eslint webpack.config.js

/Users/jrjenk5/Downloads/js-webpack/finish/webpack.config.js
  178:5  error  Parsing error: Unexpected token )

✖ 1 problem (1 error, 0 warnings)

the relevant code is


webpackConfig.plugins.push(
        new webpack.DefinePlugin({
            'process.env': {
                'NODE_ENV': JSON.stringify('production')
            }
        }),
    );

if I remove the comma that shows up after the new webpack.DefinePlugin(), on line 178 of the original file, it seems to clean up that error.

Then it complains about a missing semi-colon on line 7, because I always mess up ASI I always require them.

Here was my .eslintrc.yml file


env:
  es6: true
  node: true
extends: 'eslint:recommended'
parserOptions:
  sourceType: module
rules:
  indent:
    - error
    - 4
  linebreak-style:
    - error
    - unix
  quotes:
    - error
    - single
  semi:
    - error
    - always

So I just realized, I have an LTS version of node on my Windows box, v. 6.11.2. On my Mac at work I have a more recent version, v. 8.2.1

Reply

Yo J.R. Jenkins!

Hmmm... So, first.. this is very possible, unfortunately - because, yea, platform differences ;). About the line you mentioned... yea, that comma should not be there. It's curious it works on Unix, but seems to fail on Windows - I bet this is a Node version issue. Anyways, I'm pushing a fix right now to remove that - totally unnecessary! If you see any other issues, let me know. In Node, the / versus \ directory separators ARE important. So it's quite easy to write code that works on Unix but not Windows (or vice versa).

Cheers!

Reply
Default user avatar
Default user avatar J.R. Jenkins | weaverryan | posted 5 years ago | edited

Hey weaverryan -

Thanks for the update. Once I removed that comma on my windows box everything worked just fine, all the paths seemed to be tolerant of the difference between '/' and '\', so perhaps the use of path.resolve() moving forward is to just remove that as being a possible issue even though it "might work" currently.

I am usually on the Mac, but I had just noticed that and wanted to share. thanks again!

Reply
Default user avatar
Default user avatar Shiraats | posted 5 years ago

Hey

any idea when this will be release date

Reply

Hey Shiraats,

We're going to start releasing it in a few weeks - we were working on the new tool: Symfony Webpack Encore, that's why releasing this course is a bit delayed.

Cheers!

Reply
Default user avatar

Thank you for letting know.

I'm really looking forward to see how this all works to together.

Reply
Default user avatar
Default user avatar J.R. Jenkins | posted 5 years ago | edited

Ryan/KNP Team-

I am loving this series, and your courses overall. I keep rewatching them and taking something new away each time.

I know the answer may be controversial or you may yet answer this in one of the upcoming tutorials, but I was curious about your decision to exclude the built files from your git repository.

I am sure Deployment to multiple environments (Dev, QA, Staging, Production) could be a course all on its own (I am awaiting <a href='https://knpuniversity.com/screencast/ansistrano&#039;&gt;Animated Deployment with Ansistrano</a>), but do you actually recommend putting the build toolchain on all of those servers and doing something like this on each server:


$> git clone <repo> my-project
$> cd my-project
$> composer install [--no-dev]
$> yarn --install
$>  ./node_modules/.bin/webpack

While I can see arguments for and against it just seems like you are then adding more and more dependencies to the servers for what should generally be a deployment process.

I guess in a perfect world you would build once and then just move the built bits around, but that seems like you are opening yourself up to having different assets deployed if you are not exceedingly careful. I come from a Drupal background and we use a tool called Aegir which integrates tightly with Drush for our Deployment process, so I probably just have blinders on when it comes to different approaches.

Reply
Default user avatar
Default user avatar J.R. Jenkins | posted 5 years ago | edited

Ryan/KNP Team-

I am loving this series, and your courses overall. I keep rewatching them and taking something new away each time.

I know the answer may be controversial or you may yet answer this in one of the upcoming tutorials, but I was curious about your decision to exclude the built files from your git repository.

I am sure Deployment to multiple environments (Dev, QA, Staging, Production) could be a course all on its own (looking forward to Animated Deployment with Ansistrano, but do you actually recommend putting the build toolchain on all of those servers and doing something like this on each server:


$> git clone <repo> my-project
$> cd my-project
$> composer install
$> yarn --install
$>  ./node_modules/.bin/webpack

While I can see arguments for and against it just seems like you are then adding more and more dependencies to the servers for what should generally be a deployment process.

I guess in a perfect world you would build once and then just move the built bits around, but that seems like you are opening yourself up to having different assets deployed if you are not exceedingly careful. I come from a Drupal background and we use a tool called Aegir which integrates tightly with Drush/drush make for our Deployment process, so I probably just have blinders on when it comes to different approaches.

(sorry if this is a duplicate, comment seemed to vanish)

-1 Reply

Hey J.R. Jenkins!

No, it's a GREAT question. And you nailed it: it really comes down to your deploy mechanism. In a perfect world, it's exactly as you say: you would have some server (it could be your local machine) that fully builds everything you need, so that you have a final "artifact" (i.e. zip file with 100% of the files you need, including the built assets) that can then be just sent to a server. Heck, this artifact in a Symfony project could/should even include the warmed up cache. But, accomplishing this setup is non-trivial - we're not even that good here on KnpU. If you use a PAAS (like platform.sh), then you *do* get this: they have a build step where you can install any dependencies you need and build everything. Then, the final artifact is sent off to the real server (and so things like node are not present on the final server).

So you're not supposed to commit the built assets to your repository, based mostly on the principal that you shouldn't need to commit anything to your repository that can be perfectly rebuilt from other things that live in your repository. However, if someone told me that they needed to commit their built assets to the repo to make their deploy go more smoothly, I'd say "Well, that's not ideal, but it makes a lot of sense!". Here in KnpU, we actually don't commit the assets, and then we build them on production during deploy with Ansistrano. As you mentioned, that's not ideal, because it means we need to have things like Node installed on the server. But, that's the solution we have currently.

I'm not familiar with Aegir, but it sounds to me like this probably helps you build everything locally, and then sends the final stuff off to the remote servers. IS that right? Or does it do something different?

Cheers!

Reply
Default user avatar

Ryan-

Thanks for the follow up, and I am glad to hear I am not overthinking it too badly, I will have to give the deploy process more thought to see if we can't streamline things.

As for Aegir, the project's website is http://www.aegirproject.org/. While I am over simplifying, Aegir acts as front end to the "Drush Make" process to download Drupal and any designated add on modules or libraries as well as common migration/upgrade steps like checking dependencies, backing up the site, copying files/databases, running the update command, etc. When we build out a Drupal platform* it actually runs a 'drush make our-drush-makefile' on one server, and then copies those files to one of several web servers. But since it is just running a drush make having it build out all of the assets (i.e. SASS -> CSS) isn't really possible yet, so we tend to compile the SCSS and then commit the CSS as part of our theme. I won't fill up your comment section with more details, but if you want to know more just let me know.

* We mostly use this to manage Drupal 7 sites right now, so we haven't investigated the how the build process in Drupal 8 might change.

Reply

Yo J.R. Jenkins

Ah, interesting! I always like to hear about how other eco-systems handle things :). If you run into anything interesting or other questions along the way, let us know - I'm sure other people have the same questions.

Cheers!

Reply

Hey J.R.

Those steps are exactly what we do for KnpU during deploying, well, "git pull" except "git clone" for next deploys. And I think that's OK.Anyway, Composer and Yarn supply lock dependencies, so they will install exactly the same dependencies I have on my local machine. Well, full repository takes some HDD space, but that's not a huge problem now. The main benefit for me is that this way you can deploy project from any machine, even if you do not have working and bootstrapped project locally - it will build on the host machine during deploy. And using such tools as Ansistrano or Capistrano users won't see broken website, because those tools will switch to the new version only when it's fully bootstrapped. Or, you can replace the first step (git clone/git pull) with Rsync and do not clone repository at all, but I think running composer/yarn install is still a good idea.

I hope that helps you.

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

userVoice