The day before yesterday, I found out that the Symfony team released the Webpack Encore plugin to integrate the wonderful
Webpack tool into your application. If you are not familiar with Webpack, then I strongly recommend that you familiarize yourself with it, as it will probably solve many issues related to resource management in your project. In any case, even if you are not going to use it, knowing that it exists will be extremely useful. Very well this tool is described
here .
Introduction
At one time, I tried many different approaches and tools for managing resources. As a rule, for each project it was necessary to choose different solutions depending on the complexity of the structure. But what decision I would not choose I always had a feeling of some dissatisfaction. Always there was either a crutch, or had to adapt to the decision.
Two days ago I tried the plug-in for the symfony of the Webpack Encore project. Only two days and maybe some time later I will change my opinion about this plugin, but now being impressed I want to show you the possibilities that it offers.
Required Tools
You will need a test project on symfony> = 3.3,
NodeJS and package manager
Yarn . You can use Npm, but in this post examples will be using Yarn.
')
For the test, we will connect to the project FontAwesome, Jquery, Bootstrap and some of our own made-up resources.
Installation
First install the Webpack Encore plugin. At the root of the application:
yarn add @symfony/webpack-encore --dev
We will use SASS, so add a couple of packages:
yarn add sass-loader node-sass --dev
Do not forget to add the node_modules directory to .gitignore.
Resource Preparation
I will create the assets / directory in the application root where I will put all the necessary resources. As a result, my catalog will look like this:
+-assets/ ---+ dist/ ------+ fontawesome/ ------+ jquery/ ------+ bootstrap/
Additionally, I will create an app.scss file in the assets root / file, which will be the main resource file. It is not necessary to have a dist directory with libraries, they can be installed using Yarn. I chose this path for greater clarity.
Now you need to create instructions for the plugin. To do this, in the root of the application, create a file webpack.config.js with the following contents:
var Encore = require('@symfony/webpack-encore'); Encore .setOutputPath('web/build/') .setPublicPath('/build') .cleanupOutputBeforeBuild() .addStyleEntry('styles', './assets/app.scss') .enableSassLoader() .enableSourceMaps(!Encore.isProduction()); module.exports = Encore.getWebpackConfig();
Now you can do the resources. Edit our app.scss file:
@import "dist/fontawesome/css/font-awesome"; @import "dist/bootstrap/css/bootstrap";
Run the build. At the root of the application:
./node_modules/.bin/encore dev
If everything went smoothly, you will see in the web / build directory the styles.css file, as well as the fonts folder, where all the font-awesome fonts are referenced by font-awesome.css. If you have registered some of your own styles that use images, then these images will also be pulled into the web / build / images folder. In the resulting style files all the paths will be rewritten accordingly.
Thanks to the generated resource maps, we can comfortably use the debugger in the browser. In addition to styles, a manifest.json file will appear in the web / builds directory, about which later.
Now we need to enable the JavaScript that we need. To do this, add to the assets directory / app.js file with the following contents:
var $ = require('./dist/jquery/jquery-3.2.1'); require('./dist/bootstrap/js/bootstrap');
Now let's edit our webpack.config.js file a bit:
var Encore = require('@symfony/webpack-encore'); Encore .setOutputPath('web/build/') .setPublicPath('/build') .cleanupOutputBeforeBuild() .addEntry('scripts', './assets/app.js') .addStyleEntry('styles', './assets/app.scss') .enableSassLoader() .enableSourceMaps(!Encore.isProduction()); module.exports = Encore.getWebpackConfig();
Now restart the build:
./node_modules/.bin/encore dev
If everything went smoothly, you will get a scripts.js file in the web / builds directory.
You may have a problem with scripts that expect jQuery to be available globally. When you do var $ = require (some.js), you simply plug the script into the current context, not globally. Therefore, the scripts that you define in the templates, as well as some other libraries that are waiting for a global jQuery will not work.
There are several solutions to the problem. For all packages that you connect through require, you can provide access to $ or JQuery by adding the following instruction to the webpack.config.js file:
var Encore = require('@symfony/webpack-encore'); Encore .setOutputPath('web/build/') .autoProvidejQuery() .enableSourceMaps(!Encore.isProduction()); module.exports = Encore.getWebpackConfig();
Now everything is in order, however, the scripts that you define in the templates still will not see jQuery. In this case, you will probably need to manually add the library to the global scope. To do this, edit the file app.js:
var $ = require('./dist/jquery/jquery-3.2.1'); global.$ = global.jQuery = $; require('./dist/bootstrap/js/bootstrap');
Once again, we run the assembly and now we have everything very compactly packed, arranged in directories, we have one style file and one script file. All dependencies (fonts, images) are copied to the appropriate places.
Enable versioning:
If you enabled this feature, you will need to make some settings in the configuration of your symfony project:
# app/config/config.yml framework: # ... assets: # Symfony 3.3 json_manifest_path: '%kernel.project_dir%/web/build/manifest.json'
The file manifest.json, stores the map of the resource files to their versioned counterparts. Now connecting in your Twig template style:
<link href="{{ asset('build/styles.css') }}" rel="stylesheet" />
in fact, the following file will be included: build / styles.c1a32e.css
Connecting styles via javascript:
You can easily afford to import style files through JavaScript. On the example of our project, one could do this in app.js:
require('./app.scss'); var $ = require('./dist/jquery/jquery-3.2.1'); global.$ = global.jQuery = $; require('./dist/bootstrap/js/bootstrap');
In this case, in webpack.config.js, you do not need to add addStyleEntry. After the build, the js file and the css file of the same name will be automatically created with all the requested styles in this script.
Depla
This is a fairly holivar topic, but I’ll still touch on it. If you prefer to build on the server side, then you should add the web / build directory to .gitore and on the production server do:
./node_modules/.bin/encore production
In production mode, your scripts and styles will be further minified.
If you are critical about the development time of a project in production, then you can assemble the resources and commit the finished files to your repository.
Conclusion
This material does not claim to be used in real conditions. Each situation will have its own approaches and settings. I just wanted to show another version of resource management in the project. Those who are familiar with the webpack will probably find useful information for themselves that such a plugin has come from the symfony developers. Anyone not familiar with the webpack may be interested in this tool.
I would like to describe many things in more detail, but no matter how hard I tried, it still turned out to be too bloated post. I am ready to modify the material, if there is adequate criticism. Below are links where you can more deeply familiarize yourself with these tools:
→
Official webpack site→
Plugin documentationThanks for attention.