Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Encore - Webpack for Symfony

Encore - Webpack for Symfony

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. Encore gives you professional asset system that's a delight to use.

Mauro Cassani

June 27, 2018
Tweet

More Decks by Mauro Cassani

Other Decks in Education

Transcript

  1. E N C O R E W E B PA

    C K F O R S Y M F O N Y I N C O N T R O P U G R O M A - 2 6 G I U G N O 2 0 1 8
  2. M A U R O C A S S A

    N I H T T P S : / / G I T H U B . C O M / M A U R E T T O 7 8 A B O U T M E
  3. W H AT I S E N C O R

    E ? T H E Q U E S T I O N I N … Webpack Encore is a simpler way to integrate Webpack into your Symfony application. It wraps Webpack, giving you a clean & powerful API for bundling JavaScript modules, pre-processing CSS & JS and compiling and minifying assets. Encore gives you professional asset system that's a delight to use. Encore is inspired by Webpacker and Mix, but stays in the spirit of Webpack: using its features, concepts and naming conventions for a familiar feel. It aims to solve the most common Webpack use cases.
  4. A S S E T I C O N C

    E U P O N A T I M E … Symfony originally shipped with support for Assetic: a pure PHP library capable of processing, combining and minifying CSS and JavaScript files. And while Encore is now the recommended way of processing your assets, Assetic still works well. So what are the differences between Assetic and Encore?
  5. A S S E T I C E N C

    O R E Language Pure Php, Relies On Other Language Tools For Some Tasks Node.Js Combine Assets? Yes Yes Minify Assets? Yes (When Configured) Yes (Out-Of-The-Box) Process Sass/Less? Yes Yes Loads Js Modules? [1] No Yes Load Css Deps In Js? [1] No Yes React, Vue.Js Support? No [2] Yes Support Not Actively Maintained Actively Maintained A S S E T I C V S E N C O R E C O M PA R I S O N TA B L E
  6. F R O M L E G A C Y

    T O M O D E R N I T Y T H E G O A L <link rel="stylesheet" href="https:// stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/ bootstrap.min.css"> <link rel="stylesheet" href="https:// use.fontawesome.com/releases/v5.0.13/css/all.css"> <link rel="stylesheet" href="https:// cdnjs.cloudflare.com/ajax/libs/bootstrap- datepicker/1.8.0/css/bootstrap-datepicker.css"> // ... <script src=“https://code.jquery.com/ jquery-3.3.1.js"></script> <script src="https://stackpath.bootstrapcdn.com/ bootstrap/4.1.1/js/bootstrap.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/ libs/bootstrap-datepicker/1.8.0/js/bootstrap- datepicker.min.js"></script> <script> $(document).ready(function(){ $('.datepicker').datepicker({ ... }); }); </script> 'use strict'; require('bootstrap-datepicker'); require('../../../node_modules/bootstrap- datepicker/dist/locales/bootstrap- datepicker.it.min'); require("../../../node_modules/bootstrap- datepicker/dist/css/bootstrap- datepicker.min.css"); $('.datepicker').datepicker({ 'language': 'it' }); L E G A C Y C O D E M O D E R N C O D E
  7. F R O M L E G A C Y

    T O M O D E R N I T Y T H E G O A L <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial- scale=1.0" /> <title>{{ meta_title }}</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/ bootstrap/4.1.1/css/bootstrap.min.css"> <link rel="stylesheet" href="https://use.fontawesome.com/ releases/v5.0.13/css/all.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/ libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker.css"> <link rel="stylesheet" href="{{ asset('assets/app.css') }}"> </head> <body> ... <script src="https://code.jquery.com/jquery-3.3.1.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/ js/bootstrap.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap- datepicker/1.8.0/js/bootstrap-datepicker.min.js"></script> <script src="{{ asset('assets/app.js') }}"></script> <script> $(document).ready(function(){ $('.datepicker').datepicker({ ... }); }); </script> </body> </html> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial- scale=1.0" /> <title>{{ meta_title }}</title> <link rel="stylesheet" href="{{ asset('build/vendor.css') }}"> <link rel="stylesheet" href="{{ asset('build/app.css') }}”> <link rel="stylesheet" href="{{ asset('build/datepicker.css') }}”> </head> <body> ... <script src="{{ asset('build/manifest.js') }}”></script> <script src="{{ asset('build/vendor.js') }}”></script> <script src="{{ asset('build/app.js') }}”></script> <script src="{{ asset(‘build/datepicker.js') }}"></script> </body> </html> L E G A C Y C O D E M O D E R N C O D E
  8. G E T A PA C K A G E

    M A N A G E R B E F O R E S TA R T … To run Encore you need Node.js install and a package manager. Encore uses NPM or Yarn to compile. If you use Bower, please switch to Yarn!
  9. E N C O R E I N S TA

    L L AT I O N H O W T O I N S TA L L I T ? First, make sure you install Node.js and also the Yarn package manager. yarn add @symfony/webpack-encore --dev 1 ) I N S TA L L W I T H YA R N : npm install @symfony/webpack-encore --save-dev 2 ) I N S TA L L W I T H N P M : 3 ) I N S TA L L W I T H F L E X : composer require encore yarn install 4 ) C R E AT E A S Y M F O N Y S K E L E T O N A P P L I C AT I O N : composer create-project symfony/website-skeleton my-project
  10. T H E P R O J E C T

    S T R U C T U R E A F T E R I N S TA L L E N C O R E , TA K E A L O O K AT … | —- /assets | —- /bin | —- /config | —- /node_modules | —- /public | —- /build | —- index.php | —- /src | —- /tests | —- /var | —- /vendor | —- .env | —- .env.dist | —- .gitignore | —- composer.json | —- package.json | —- webpack.config.js | —- yarn.lock This is the structure of a classic Symfony 4 web application:
  11. R U N E N C O R E H

    O W T O R U N I T ? In your package.json file are defined three shortcuts: yarn encore [env] [—-option] { .. "scripts": { "dev-server": "encore dev-server", "dev": "encore dev", "watch": "encore dev --watch", "build": "encore production" } } To run encore type this on your root project:
  12. W E B PA C K . C O N

    F I G . J S T H E C O N F I G U R AT I O N F I L E The webpack.config.js is the config file of Encore. It lives in the root of your project. Here is a sample: // webpack.config.js var Encore = require('@symfony/webpack-encore'); Encore // the project directory where all compiled assets will be stored .setOutputPath('public/build/') // the public path used by the web server to access the previous directory .setPublicPath('/build') // will create public/build/app.js and public/build/app.css .addEntry('app', './assets/js/app.js') // allow legacy applications to use $/jQuery as a global variable .autoProvidejQuery() // enable source maps during development .enableSourceMaps(!Encore.isProduction()) // empty the outputPath dir before each build .cleanupOutputBeforeBuild() // show OS notifications when builds finish/fail .enableBuildNotifications() // create hashed filenames (e.g. app.abc123.css) // .enableVersioning() // allow sass/scss files to be processed // .enableSassLoader() ; // export the final configuration module.exports = Encore.getWebpackConfig();
  13. I N I T I A L S E T

    T I N G S T H E C O N F I G U R AT I O N F I L E SETUP THE OUTPUT PATH WHERE YOUR ASSETS WILL BE COMPILED: setOutputPath('public/build/') setPublicPath('/build') the project directory where all compiled assets will be stored the public path used by the web server to access the previous directory enableBuildNotifications() A VERY USEFUL TOOLS IS: show OS notifications when builds finish/fail
  14. E N A B L I N G S A

    S S / L E S S C O M P I L I N G T H E C O N F I G U R AT I O N F I L E enableSassLoader(function(options) { // https://github.com/sass/node-sass#options // options.includePaths = [...] }) And then enable the SASS/SCSS file compiling: To use the Sass pre-processor, install the dependencies: yarn add --dev sass-loader node-sass yarn add --dev less-loader less enableLessLoader(function(options) { // https://github.com/webpack-contrib/less-loader#examples // http://lesscss.org/usage/#command-line-usage-options // options.relativeUrls = false; }) And then enable the LESS file compiling: If you want to use Less, install pre-processor:
  15. E N A B L I N G S O

    U R C E M A P S T H E C O N F I G U R AT I O N F I L E Source maps allow browsers to access the original code related to some asset (e.g. the Sass code that was compiled to CSS or the TypeScript code that was compiled to JavaScript). Source maps are useful for debugging purposes but unnecessary when executing the application in production. Encore inlines source maps in the compiled assets only in the development environment, but you can control this behavior with the enableSourceMaps() method: enableSourceMaps(!Encore.isProduction()) enableSourceMaps(true) this is the default behavior... ... but you can override it by passing a boolean value
  16. A D D E N T R I E S

    T H E C O N F I G U R AT I O N F I L E To add entries just use addEntry or addStyleEntry method: Encore // ... .addEntry('page1', 'assets/js/page1.js') .addEntry(‘page2',['assets/js/comp1.js','assets/js/comp1.js']) // ... .addStyleEntry('stylesheet1', 'assets/scss/stylesheet1.scss') .addStyleEntry('stylesheet2', 'assets/scss/stylesheet2.scss') addEntry can produce both css and js files, depends of source javascript file. addStyleEntry works only with css files.
  17. C S S I N J AVA S C R

    I P T F I L E ? T H E C O N F I G U R AT I O N F I L E In your javascript source files you can require css files. Encore will process the file and will create a css file and a js file. The compilation of sample code below will produce two separate files: app.css and app.js: // ./assets/app.js ——> ./public/build/app.css // ——> ./public/build/app.js // js require('../js/Components/chart.js'); require('../js/Components/dashboard.js'); require('../js/Components/misc.js'); require('../js/Components/off-canvas.js'); require('../js/Components/uploader.js'); // scss require('../scss/style.scss');
  18. S H A R E D E N T R

    I E S T H E C O N F I G U R AT I O N F I L E If you have multiple entry files and each requires the same dependencies, ex. jquery, you can extract these common libraries to a "shared" entry file that's included on every page by using createSharedEntry method: Encore // ... // this creates a ‘vendor.js' file with jquery and the bootstrap JS module // these modules will *not* be included in page1.js or page2.js anymore .createSharedEntry('vendor', [ 'jquery', 'bootstrap', // you can also extract CSS - this will create a 'vendor.css' file // this CSS will *not* be included in page1.css or page2.css anymore 'bootstrap-sass/assets/stylesheets/_bootstrap.scss' ]) In your application you MUST include manifest.js file: this file is needed so that Webpack knows how to load those shared modules.
  19. A S S E T S V E R S

    I O N I N G T H E C O N F I G U R AT I O N F I L E To enable versioning of assets: enableVersioning() cleanupOutputBeforeBuild() To link to these assets, Encore creates a manifest.json file with a map to the new filenames. Here is a sample code: If you're using Symfony, just activate the json_manifest_file versioning strategy in framework file: # config/packages/framework.yaml framework: # ... assets: # feature is supported in Symfony 3.3 and higher json_manifest_path: '%kernel.project_dir%/public/build/manifest.json' { "build/app.js": "/build/app.123abc.js", "build/dashboard.css": "/build/dashboard.a4bf2d.css" }
  20. J Q U E RY A N D L E

    G A C Y A P P S T H E C O N F I G U R AT I O N F I L E Inside Webpack, when you require a module, it does not (usually) set a global variable. Instead, it just returns a value: autoProvideJQuery() // this loads jquery, but does *not* set a global $ or jQuery variable const $ = require('jquery'); In practice, this will cause problems with some outside libraries that rely on jQuery to be global. It will be a problem if some of your JavaScript isn't being processed through Webpack (e.g. you have some JavaScript in your templates). So, when working with legacy applications, you may need to add the following to webpack.config.js: Internally, this autoProvidejQuery() method calls the autoProvideVariables() method from Encore.
  21. P R O V I D E G L O

    B A L VA R I A B L E S T H E C O N F I G U R AT I O N F I L E You can use autoProvideVariables from Webpack to expose global variables to use in your assets. Take a look at this example: Encore // you can use this method to provide other common global variables, // such as '_' for the 'underscore' library .autoProvideVariables({ $: 'jquery', jQuery: 'jquery', 'window.jQuery': 'jquery', }) // ... ; And now you can use $ or jQuery variables in your scripts that requires jQuery. Internally Encore makes this transformation: function($){ // .. }(jQuery); function($){ // .. }(require('jquery'));
  22. A D D I N G P L U G

    I N S T H E C O N F I G U R AT I O N F I L E You can add Webpack plugins by using addPlugin method. Please take a look a this example: var Encore = require('@symfony/webpack-encore'); const CopyWebpackPlugin = require('copy-webpack-plugin'); Encore // other code .. // plugins .addPlugin( new CopyWebpackPlugin([ { from: './assets/images', to: 'images' } ]) ) ; // export module.exports = Encore.getWebpackConfig();
  23. B E S T P R A C T I

    E S S O M E T I P S • Deploy only builded files; • Use versioning; • Enable long-term caching for browser on your server; DEPLOY FILES • Organize your Javascripts to make them reusable; • Use the createSharedEntry option; • Create a vendor entry; • Create a general app entry; • Create specific entires for specific pages. Only an specific entry per page;
  24. L I V E C O D I N G

    ! H O P E A L L W O R K S ! A N D N O W …
  25. U S E F U L R E S O

    U R C E S D O C U M E N TAT I O N • http://symfony.com/doc/current/frontend.html (Symfony official documentation) • https://github.com/symfony/webpack-encore (Encore official GitHub repo) • https://knpuniversity.com/screencast/webpack-encore (13 videos) • https://webpack.js.org/concepts/ (Webpack offical documentation)
  26. T H A N K Y O U ! A

    N Y Q U E S T I O N S ? T H E E N D