Symfony Webpack encore going from global variables to webpack js management and node packages

Going from a JS strewn over the project to a single app.js and app.css that will hold all the dependencies and webpack which is going to manage this in an efficient manner.

Modules in JS – importing, exporting. Why is it a first step to managing node_module as in PHP’s composer

module.js

module.exports = function() {
   return 'A message from a module which returns a function, but can return an object or a string typically';
}

When importing the module in a different .js file:

const importedModule = require("./module.js");

The dot slash in require is important as it means that we’re improting the js file. If we skipped that it would have meant we’re trying to import a third party module.

One more thing, the “.js” part can be omitted. JavaScript knows here what we mean and it’s going to import the js file even if we don’t provide this extension in require function.

const importedModule = require("./module");

Now, our module.js can be modified and it’s syntax refactored. Instead of modules.exports

module.js

export default function() {
   return 'A message from a module which returns a function, but can return an object or a string typically';
}

With default the module (file) can export something more that one function but most of the times you will want to export just one thing. In the file that uses the module this now can be expressed like that:

import importedModule from './module';

importedModule – this is an arbitrary name

./module or ./module.js – still the same file that we’re importing from

If the import source is without folder references, just with a name:

import importedModule from 'module';

the library would be looked for in “node_modules” directory.

Which code from the package is then imported, which file?

in package.json for every packaged the there is a object’s key called “main” which specifies which file should be imported, for jQuery it is “dist/jquery.js”.

Now if we wanted to import jquery from node_modules we’d do it like that:

import $ from 'jquery';

A webpack contruct we could use here if we needed the global variables (old school):

global.$ = $;

since we already imported ‘jquery‘ library to a variable called $ then we can now use in the assignment above (the global.$ is a webpack feature)

Why bootstrap functions don’t work with jQuery even though it is included via script tag?

When you include bootstrap js code via <script> tag it expects that a global variable “$” is set.

How do I know what’s the name of the package in yarn?

Go to https://yarnpkg.com/en/packages?q=bootstrap&p=1 and have a look there.

add the package via yarn with: yarn add bootstrap@4.1.3

Now we can add in app.js:

Let’s import bootstrap node package to the project

import ‘bootstrap’; (since this is a jQuery plugin) and jQuery plugins are not standard because there DO NOT return value. Instead they modify jQuery and add functions to it.

Now, bootstrap.js depends on popper.js and jQuery.

  • jQuery is already there in node_modules
  • popper.js is not, therefore webpack build was failing.

Not in all cases will the dependency of one node packge be automatically resolved. It’s called a “peer dependency”.

We can now add popper.js with:

yarn add popper.js –dev

Now webpack is optimizing our build with “code splitting”. When it discovers it’s more efficienty to split the code to app and vendor part you will have:

  • app.js
  • vendor~app.js (which can be cached then more efficiently as it doesn’t change that often as app specific code)

Webpack’s algorithm determines whether to spli the js code depending on the size of the package. (this comes from a webpack plugin “splits chunks plugin“.

The plugin has a default config, which we can modify in Symfony Webpack Encore.

at the end of webpack.config.js (which is a config from a Symfony Webpack Encore) there is a line that generates the original’s webpack config:

module.exports = Encore.getWebpackConfig();

If we wanted to modify the setting of the plugin we could do it like that:

const config = Encore.getWebpackConfig();
config.optimization.slitChunks.minSize = 2000;
module.exports = config;

Or this could be done with .configureSplitChunks using Encore’s config.

webpack.config.js

Encore.
    // ...
    .splitEntryChunks()
    .configureSplitChunks(function(splitChunks) {
        splitChunks.minSize = 20000;
    })
    // ...
;

module.exports = Encore.getWebpackConfig();

Importing css files with webpack

It’s best to:

  • import one .css file in the .js file that’s under webpack’s control

Importing other css files from node_modules

In app.css (main file which imports other files) the method to import other files we can you import statement, just like that:

@import ‘~/bootstrap/dist/css/bootstrap.css’

which can be shortened to

@import ‘~bootstrap’

thanks to a feature added to Symfony Webpack Encore which imports either style, main or scss files depending where we’re importing it. Since we’re here in app.css then style.css is used.

Note: only some packages enable these keys like “style”, “sass”, “main”. Bootstrap does.

The difference with importing node js modules here is the:

  • @ symbol at the beginning
  • ~/ – this just means we’re looking in node_modules
  • bootstrap – actual name of the node package
  • /dist/css/bootstrap.css – the path to the css file we’re importing to the project

whereas for node JavaScript module it was just

import someReturnObjOrFunOrString from ‘bootstrap’;

Webpack importing a package and automatically imported fonts

When we import a package from node_packages like @import ‘~font-awesome’ we then, can observe that in the background, the fonts are imported separately into public/build/fonts. Also adds hash to the name of the files, based on the files’ contents – which is used for browser cache busting.

public/build/ – the path that we specified in webpack.config.js with setOutputPath.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create your website with WordPress.com
Get started
%d bloggers like this: