From d8ddb85ffc4a09afe3f0b60d3fb51e1ad6b8926c Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 10 Jun 2017 14:09:15 -0400 Subject: [PATCH 1/5] Initial import of encore docs --- frontend.rst | 74 +++++++++- frontend/encore/babel.rst | 30 ++++ frontend/encore/bootstrap.rst | 116 ++++++++++++++++ frontend/encore/cdn.rst | 47 +++++++ frontend/encore/css-preprocessors.rst | 49 +++++++ frontend/encore/dev-server.rst | 31 +++++ frontend/encore/installation.rst | 32 +++++ frontend/encore/legacy-apps.rst | 53 +++++++ frontend/encore/page-specific-assets.rst | 45 ++++++ frontend/encore/postcss.rst | 41 ++++++ frontend/encore/reactjs.rst | 26 ++++ frontend/encore/server-data.rst | 34 +++++ frontend/encore/shared-entry.rst | 43 ++++++ frontend/encore/simple-example.rst | 167 +++++++++++++++++++++++ frontend/encore/sourcemaps.rst | 27 ++++ frontend/encore/versioning.rst | 61 +++++++++ 16 files changed, 874 insertions(+), 2 deletions(-) create mode 100644 frontend/encore/babel.rst create mode 100644 frontend/encore/bootstrap.rst create mode 100644 frontend/encore/cdn.rst create mode 100644 frontend/encore/css-preprocessors.rst create mode 100644 frontend/encore/dev-server.rst create mode 100644 frontend/encore/installation.rst create mode 100644 frontend/encore/legacy-apps.rst create mode 100644 frontend/encore/page-specific-assets.rst create mode 100644 frontend/encore/postcss.rst create mode 100644 frontend/encore/reactjs.rst create mode 100644 frontend/encore/server-data.rst create mode 100644 frontend/encore/shared-entry.rst create mode 100644 frontend/encore/simple-example.rst create mode 100644 frontend/encore/sourcemaps.rst create mode 100644 frontend/encore/versioning.rst diff --git a/frontend.rst b/frontend.rst index ce1253a95b3..7f1535579a7 100644 --- a/frontend.rst +++ b/frontend.rst @@ -1,5 +1,75 @@ -Front-end -========= +Managing CSS and JavaScript +=========================== + +Symfony ships with a pure-JavaScript library - called Webpack Encore - that makes +working with CSS and JavaScript a joy. You can use it, use something else, or just +create static CSS and JS files in your ``web/`` directory and include them in your +templates. + +Webpack Encore +============== + +`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. + +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. + +.. tip:: + + Encore is made by `Symfony`_ and works *beautifully* in Symfony applications. + But it can easily be used in any application... in any language! + +Documentation +------------- + +Getting Started +............... + +* :doc:`Installation ` +* :doc:`First Example ` + +Adding more Features +.................... + +* :doc:`CSS Preprocessors: SASS, LESS, etc ` +* :doc:`PostCSS and autoprefixing ` +* :doc:`Enabling React.js ` +* :doc:`Configuring Babel ` +* :doc:`Sourcemaps ` + +Optimizing +.......... + +* :doc:`Versioning and manifest.json ` +* :doc:`Using A CDN ` +* :doc:`Creating a "Shared" entry for re-used modules ` + +Guides +...... + +* :doc:`Using Bootstrap CSS & JS ` +* :doc:`Creating Page-Specific CSS/JS ` +* :doc:`jQuery and Legacy Applications ` +* :doc:`Passing Information from Twig to JavaScript ` +* :doc:`webpack-dev-server and Hot Module Replacement (HMR) ` + +Full API +........ + +* `Full API`_: https://github.com/symfony/webpack-encore/blob/master/index.js + +.. _`Webpack Encore`: https://www.npmjs.com/package/@symfony/webpack-encore +.. _`Webpack`: https://webpack.js.org/ +.. _`Webpacker`: https://github.com/rails/webpacker +.. _`Mix`: https://laravel.com/docs/5.4/mix +.. _`Symfony`: http://symfony.com/ +.. _`Full API`: https://github.com/symfony/webpack-encore/blob/master/index.js + .. toctree:: :maxdepth: 1 diff --git a/frontend/encore/babel.rst b/frontend/encore/babel.rst new file mode 100644 index 00000000000..0fd00cc2c6d --- /dev/null +++ b/frontend/encore/babel.rst @@ -0,0 +1,30 @@ +Configuring Babel +================= + +`Babel`_ is automatically configured for all ``.js`` and ``.jsx`` files via the +``babel-loader`` with sensible defaults (e.g. with the ``env`` preset and +``react`` if requested). + +Need to extend the Babel configuration further? The easiest way is via +``configureBabel()``: + +.. code-block:: javascript + + // webpack.config.js + // ... + + Encore + // ... + + // modify the default Babel configuration + .configureBabel(function(babelConfig) { + babelConfig.presets.push('es2017'); + }) + ; + +You can also create a standard ``.babelrc`` file at the root of your project. +Just make sure to configure it with all the presets you need: as soon as a +``.babelrc`` is present, Encore can no longer add *any* Babel configuration for +you! + +.. _`Babel`: http://babeljs.io/ diff --git a/frontend/encore/bootstrap.rst b/frontend/encore/bootstrap.rst new file mode 100644 index 00000000000..6f3b5fc0100 --- /dev/null +++ b/frontend/encore/bootstrap.rst @@ -0,0 +1,116 @@ +Using Bootstrap CSS & JS +======================== + +Want to use Bootstrap (or something similar) in your project? No problem! +First, install it. To be able to customize things further, we'll install +``bootstrap-sass``: + +.. code-block:: terminal + + $ yarn add bootstrap-sass --dev + +Importing Bootstrap SASS +------------------------ + +Now that ``bootstrap-sass`` lives in your ``node_modules`` directory, you can +import it from any SASS or JavaScript file. For example, if you're already have +a ``global.scss`` file, import it from there: + +.. code-block:: css + + // assets/css/global.scss + + // customize some Bootstrap variables + $brand-primary: darken(#428bca, 20%); + + // the ~ allows you to reference things in node_modules + @import '~bootstrap-sass/assets/stylesheets/bootstrap'; + +That's it! This imports the ``node_modules/bootstrap-sass/assets/stylesheets/_bootstrap.scss`` +file into ``global.scss``. You can even customize the Bootstrap variables first! + +.. tip:: + + If you don't need *all* of Bootstrap's features, you can include specific files + in the ``bootstrap`` directory instead - e.g. ``~bootstrap-sass/assets/stylesheets/bootstrap/alerts``. + +After including ``bootstrap-sass``, your webpack builds might become slow. To fix +this, you can use the ``resolve_url_loader`` option: + +.. code-block:: diff + + // webpack.config.js + Encore + + enableSassLoader({ + + 'resolve_url_loader' => false + + }) + ; + +This disables the ``resolve-url-loader`` in Webpack, which means that any +``url()`` paths in your SASS files must now be relative to the original source +entry file instead of whatever file you're inside of (see `Problems with url()`_). +To load Bootstrap, you'll need to override the path to its icons: + +.. code-block:: diff + + // assets/css/global.scss + + + $icon-font-path: "~bootstrap-sass/assets/fonts/bootstrap/"; + + + // set if you're also including font-awesome + + // $fa-font-path: "~font-awesome/fonts"; + + @import '~bootstrap-sass/assets/stylesheets/bootstrap'; + +Importing Bootstrap JavaScript +------------------------------ + +Bootstrap JavaScript requires jQuery, so make sure you have this installed: + +.. code-block:: terminal + + $ yarn add jquery --dev + +Next, make sure call ``.autoProvidejQuery()`` in your ``webpack.config.js`` file: + +.. code-block:: diff + + // webpack.config.js + Encore + // ... + + .autoProvidejQuery() + +This is needed because Bootstrap expects jQuery to be available as a global +variable. Now, require bootstrap from any of your JavaScript files: + +.. code-block:: javascript + + // main.js + + var $ = require('jquery'); + // JS is equivalent to the normal "bootstrap" package + // no need to set this to a variable, just require it + require('bootstrap-sass'); + + // or you can include specific pieces + // require('bootstrap-sass/javascripts/bootstrap/tooltip'); + // require('bootstrap-sass/javascripts/bootstrap/popover'); + + $(document).ready(function() { + $('[data-toggle="popover"]').popover(); + }); + +Thanks to ``autoProvidejQuery()``, you can require any other jQuery +plugins in a similar way: + +.. code-block:: javascript + + // ... + + // require the JavaScript + require('bootstrap-star-rating'); + // require 2 CSS files needed + require('bootstrap-star-rating/css/star-rating.css'); + require('bootstrap-star-rating/themes/krajee-svg/theme.css'); + +.. _`Problems with url()`: https://github.com/webpack-contrib/sass-loader#problems-with-url diff --git a/frontend/encore/cdn.rst b/frontend/encore/cdn.rst new file mode 100644 index 00000000000..f387f84d758 --- /dev/null +++ b/frontend/encore/cdn.rst @@ -0,0 +1,47 @@ +Using a CDN +=========== + +Are you deploying to a CDN? That's awesome :) - and configuring +Encore for that is easy. Once you've made sure that your built files +are uploaded to the CDN, configure it in Encore: + +.. code-block:: diff + + // webpack.config.js + // ... + + Encore + .setOutputPath('web/build/') + // in dev mode, don't use the CDN + .setPublicPath('/build'); + // ... + ; + + + if (Encore.isProduction()) { + + Encore.setPublicPath('https://my-cool-app.com.global.prod.fastly.net'); + + + + // guarantee that the keys in manifest.json are *still* + + // prefixed with build/ + + // (e.g. "build/dashboard.js": "https://my-cool-app.com.global.prod.fastly.net/dashboard.js") + + Encore.setManifestKeyPrefix('build/'); + + } + +That's it! Internally, Webpack will now know to load assets from your CDN - +e.g. ``https://my-cool-app.com.global.prod.fastly.net/dashboard.js``. + +.. note:: + + It's still your responsibility to put your assets on the CDN - e.g. by + uploading them or by using "origin pull", where your CDN pulls assets + directly from your web server. + +You *do* need to make sure that the ``script`` and ``link`` tags you include on your +pages also uses the CDN. Fortunately, the ``manifest.json`` paths are +updated to point to the CDN. In Symfony, as long as you've configured +:doc:`Asset Versioning `, you're done! The ``manifest.json`` +file includes the full CDN URL: + +.. code-block:: js + + {# Your script/link tags don't need to change at all to support the CDN #} + diff --git a/frontend/encore/css-preprocessors.rst b/frontend/encore/css-preprocessors.rst new file mode 100644 index 00000000000..d9baa1c6ea5 --- /dev/null +++ b/frontend/encore/css-preprocessors.rst @@ -0,0 +1,49 @@ +CSS Preprocessors: Sass, LESS, etc +================================== + +Using Sass +---------- + +To use the Sass pre-processor, install the dependencies: + +.. code-block:: terminal + + $ yarn add --dev sass-loader node-sass + +And enable it in ``webpack.config.js``: + +.. code-block:: javascript + + // webpack.config.js + // ... + + Encore + // ... + .enableSassLoader() + ; + +That's it! All files ending in ``.sass`` or ``.scss`` will +be processed. + +Using LESS +---------- + +To use the LESS pre-processor, install the dependencies: + +.. code-block:: terminal + + $ yarn add --dev less-loader less + +And enable it in ``webpack.config.js``: + +.. code-block:: javascript + + // webpack.config.js + // ... + + Encore + // ... + .enableLessLoader() + ; + +That's it! All files ending in ``.less`` will be pre-processed. diff --git a/frontend/encore/dev-server.rst b/frontend/encore/dev-server.rst new file mode 100644 index 00000000000..756cdd6a9d2 --- /dev/null +++ b/frontend/encore/dev-server.rst @@ -0,0 +1,31 @@ +Using webpack-dev-server and HMR +================================ + +While developing, instead of using ``encore dev --watch``, you can +instead use the `webpack-dev-server`_: + +.. code-block:: terminal + + $ ./node_modules/.bin/encore dev-server + +This serves the built assets from a new server at ``http://localhost:8080`` +(it does not actually write any files to disk). This means your +``script`` and ``link`` tags need to change to point to this. + +If you've activated the :ref:`manifest.json versioning ` +you're done: the paths in your templates will automatically point to the dev server. + +You can also pass options to the ``dev-server`` command: any options that +are supported by the normal `webpack-dev-server`_. For example: + +.. code-block:: terminal + + $ ./node_modules/.bin/encore dev-server --https --port 9000 + +This will start a server at ``https://localhost:9000``. + +.. note:: + + Hot module replacement is not currently supported. + +.. _`webpack-dev-server`: https://webpack.js.org/configuration/dev-server/ diff --git a/frontend/encore/installation.rst b/frontend/encore/installation.rst new file mode 100644 index 00000000000..8d9cc283aec --- /dev/null +++ b/frontend/encore/installation.rst @@ -0,0 +1,32 @@ +Installation +============ + +First, make sure you `install Node.js`_ and also the `yarn package manager`_. + +Then, install Encore into your project with yarn: + +.. code-block:: terminal + + $ yarn add @symfony/webpack-encore --dev + +.. note:: + + If you want to use `npm`_ instead of `yarn`_, replace ``yarn add xxx --dev`` by + ``npm install xxx --save-dev``. + +This command creates (or modifies) a ``package.json`` file and downloads +dependencies into a ``node_modules/`` directory. When using Yarn, a file called +``yarn.lock`` is also created/updated. When using npm 5, a ``package-lock.json`` +file is created/updated. + +.. tip:: + + You should commit ``package.json`` and ``yarn.lock`` (or ``package-lock.json`` + if using npm) to version control, but ignore ``node_modules/``. + +Next, create your ``webpack.config.js`` in :doc:`/frontend/encore/simple-example`! + +.. _`install Node.js`: https://nodejs.org/en/download/ +.. _`yarn package manager`: https://yarnpkg.com/lang/en/docs/install/ +.. _`npm`: https://www.npmjs.com/ +.. _`yarn`: https://yarnpkg.com/ diff --git a/frontend/encore/legacy-apps.rst b/frontend/encore/legacy-apps.rst new file mode 100644 index 00000000000..7c0d189f807 --- /dev/null +++ b/frontend/encore/legacy-apps.rst @@ -0,0 +1,53 @@ +jQuery and Legacy Applications +============================== + +Some legacy JavaScript applications use programming practices that don't play +well with the new practices promoted by Webpack. The most common of these +problems is using code (e.g. jQuery plugins) that assume that jQuery is already +available via the the ``$`` or ``jQuery`` global variables. If those variables +are not defined, you'll get these errors: + +.. code-block:: text + + Uncaught ReferenceError: $ is not defined at [...] + Uncaught ReferenceError: jQuery is not defined at [...] + +Instead of rewriting everything, Encore allows for a different solution. Thanks +to the ``autoProvidejQuery()`` method, whenever a JavaScript file uses the ``$`` +or ``jQuery`` variables, Webpack automatically requires ``jquery`` and creates +those variables for you. + +So, when working with legacy applications, you may need to add the following to +``webpack.config.js``: + +.. code-block:: diff + + Encore + // ... + + .autoProvidejQuery() + ; + +Internally, this ``autoProvidejQuery()`` method uses the ``autoProvideVariables()`` +method from Encore. In practice, it's equivalent to doing: + +.. code-block:: javascript + + Encore + // you can use this method to provide other common global variables, + // such as '_' for the 'underscore' library + .autoProvideVariables({ + $: 'jquery', + jQuery: 'jquery' + }) + // ... + ; + +If you also need to provide access to ``$`` and ``jQuery`` variables outside of +JavaScript files processed by Webpack, you must create the global variables +yourself in some file loaded before the legacy JavaScript code. For example, you +can define a ``common.js`` file processed by Webpack and loaded in every page +with the following content: + +.. code-block:: javascript + + window.$ = window.jQuery = require('jquery'); diff --git a/frontend/encore/page-specific-assets.rst b/frontend/encore/page-specific-assets.rst new file mode 100644 index 00000000000..c59a7674db9 --- /dev/null +++ b/frontend/encore/page-specific-assets.rst @@ -0,0 +1,45 @@ +Creating Page-Specific CSS/JS +============================= + +If you're creating a single page app (SPA), then you probably only need to define +*one* entry in ``webpack.config.js``. But if you have multiple pages, you might +want page-specific CSS and JavaScript. + +For example, suppose you have a checkout page that has its own JavaScript. Create +a new ``checkout`` entry: + +.. code-block:: diff + + // webpack.config.js + + Encore + // an existing entry + .addEntry('app', './assets/js/main.js') + // a global styles entry + .addStyleEntry('global', './assets/css/global.scss') + + + .addEntry('checkout', './assets/js/checkout.js') + ; + +Inside ``checkout.js``, add or require the JavaScript and CSS you need. +Then, just include a ``script`` tag for ``checkout.js`` on the checkout +page (and a ``link`` tag for ``checkout.css`` if you import any CSS). + +Multiple Entries Per Page? +-------------------------- + +Typically, you should include only *one* entry JavaScript per page. This means +the checkout page will include ``checkout.js``, but will *not* include the +``app.js`` that's used on the other pages. Think of the checkout page as its +own "app", where ``checkout.js`` includes all the functionality you need. + +However, if there is some global JavaScript that you want included on *every* +page, you *can* create an entry that contains that code and include both that +entry *and* your page-specific entry. For example, suppose that the ``app`` +entry above contains JavaScript you want on every page. In that case, include +both ``app.js`` and ``checkout.js`` on the checkout page. + +.. tip:: + + Be sure to create a :doc:`shared entry ` to avoid duplicating + the Webpack bootstrap logic and any shared modules. diff --git a/frontend/encore/postcss.rst b/frontend/encore/postcss.rst new file mode 100644 index 00000000000..9ad8328346c --- /dev/null +++ b/frontend/encore/postcss.rst @@ -0,0 +1,41 @@ +PostCSS and autoprefixing (postcss-loader) +========================================== + +`PostCSS`_ is a CSS post-processing tool that can transform your CSS in a lot +of cool ways, like `autoprefixing`_, `linting`_ and more! + +First, download ``postcss-loader`` and any plugins you want, like ``autoprefixer``: + +.. code-block:: terminal + + $ yarn add --dev postcss-loader autoprefixer + +Next, create a ``postcss.config.js`` file at the root of your project: + +.. code-block:: javascript + + module.exports = { + plugins: { + // include whatever plugins you want + // but make sure you install these via yarn or npm! + autoprefixer: {} + } + } + +Then, Enable the loader in Encore! + +.. code-block:: diff + + // webpack.config.js + + Encore + // ... + + .enablePostCssLoader() + ; + +That's it! The ``postcss-loader`` will now be used for all CSS, Sass, etc +files. + +.. _`PostCSS`: http://postcss.org/ +.. _`autoprefixing`: https://github.com/postcss/autoprefixer +.. _`linting`: https://stylelint.io/ diff --git a/frontend/encore/reactjs.rst b/frontend/encore/reactjs.rst new file mode 100644 index 00000000000..dd2877b0d06 --- /dev/null +++ b/frontend/encore/reactjs.rst @@ -0,0 +1,26 @@ +Enabling React.js +================= + +Using React? Make sure you have React installed, along with the +`babel-preset-react`_: + +.. code-block:: terminal + + $ yarn add --dev react react-dom prop-types babel-preset-react + +Enable react in your ``webpack.config.js``: + +.. code-block:: javascript + + // webpack.config.js + // ... + + Encore + // ... + .enableReactPreset() + ; + +That's it! Your ``.js`` and ``.jsx`` files will now be transformed through +``babel-preset-react``. + +.. _`babel-preset-react`: https://babeljs.io/docs/plugins/preset-react/ diff --git a/frontend/encore/server-data.rst b/frontend/encore/server-data.rst new file mode 100644 index 00000000000..5c768c24cce --- /dev/null +++ b/frontend/encore/server-data.rst @@ -0,0 +1,34 @@ +Passing Information from Twig to JavaScript +=========================================== + +In Symfony applications, you may find that you need to pass some dynamic data +(e.g. user information) from Twig to your JavaScript code. One great way to pass +dynamic configuration is by storing information in ``data`` attributes and reading +them later in JavaScript. For example: + +.. code-block:: twig + +
+ +
+ +Fetch this in JavaScript: + +.. code-block:: javascript + + // jquery isn't required, but makes things simple + var $ = require('jquery'); + + $(document).ready(function() { + var isAuthenticated = $('.js-user-rating').data('is-authenticated'); + }); + +There is no size limit for the value of the ``data-`` attributes, so you can +store any content. In Twig, use the ``html_attr`` escaping strategy to avoid messing +with HTML attributes: + +.. code-block:: twig + +
+ +
diff --git a/frontend/encore/shared-entry.rst b/frontend/encore/shared-entry.rst new file mode 100644 index 00000000000..7b463d31a47 --- /dev/null +++ b/frontend/encore/shared-entry.rst @@ -0,0 +1,43 @@ +Creating a Shared Commons Entry +=============================== + +Suppose you have multiple entry files and *each* requires ``jquery``. In this +case, *each* output file will contain jQuery, slowing down your user's experience. +In this case, you can *extract* these common libraries to a "shared" entry file +that's included on every page: + +.. code-block:: javascript + + Encore + // ... + .addEntry('page1', 'asssets/js/page1.js') + .addEntry('page2', 'asssets/js/page2.js') + + // 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']) + +As soon as you make this change, you need to include two extra JavaScript files +on your page before any other JavaScript file: + +.. code-block:: twig + + + + + + + + +The ``vendor.js`` file contains all the common code that has been extracted from +the other files, so it's obvious that it must be included. The other file (``manifest.js``) +is less obvious: it's needed so that Webpack knows how to load those shared modules. + +.. tip:: + + The ``vendor.js`` file works best when its contents are changed *rarely* + and you're using :ref:`long-term caching `. Why? + If ``vendor.js`` contains application code that *frequently* changes, then + (when using versioning), its filename hash will frequently change. This means + your users won't enjoy the benefits of long-term caching for this file (which + is generally quite large). diff --git a/frontend/encore/simple-example.rst b/frontend/encore/simple-example.rst new file mode 100644 index 00000000000..a7ee527a18c --- /dev/null +++ b/frontend/encore/simple-example.rst @@ -0,0 +1,167 @@ +First Example +============= + +Imagine you have a simple project with one CSS and one JS file, organized into +an ``assets/`` directory: + +* ``assets/js/main.js`` +* ``assets/css/global.scss`` + +With Encore, we can easily minify these files, pre-process ``global.scss`` +through SASS and a *lot* more. + +Configuring Encore/Webpack +-------------------------- + +Create a new file called ``webpack.config.js`` at the root of your project. +Inside, use Encore to help generate your Webpack configuration. + +.. code-block:: javascript + + // webpack.config.js + var Encore = require('@weaverryan/webpack-remix'); + + Encore + // directory where should all compiled assets will be stored + .setOutputPath('web/build/') + + // what's the public path to this directory (relative to your project's document root dir) + .setPublicPath('/build') + + // empty the outputPath dir before each build + .cleanupOutputBeforeBuild() + + // will output as web/build/app.js + .addEntry('app', './assets/js/main.js') + + // will output as web/build/global.css + .addStyleEntry('global', './assets/css/global.scss') + + // allow sass/scss files to be processed + .enableSassLoader() + + // allows legacy applications to use $/jQuery as a global variable + .autoProvidejQuery() + + .enableSourceMaps(!Encore.isProduction()) + + // create hashed filenames (e.g. app.abc123.css) + // .enableVersioning() + ; + + // export the final configuration + module.exports = Encore.getWebpackConfig(); + +This is already a rich setup: it outputs 2 files, uses the +SASS pre-processor and enables sourcemaps to help debugging. + +.. _encore-build-assets: + +To build the assets, use the ``encore`` executable: + +.. code-block:: terminal + + # compile assets once + $ ./node_modules/.bin/encore dev + + # recompile assets automatically when files change + $ ./node_modules/.bin/encore dev --watch + + # compile assets, but also minify & optimize them + $ ./node_modules/.bin/encore production + +.. note:: + + Restart ``encore`` each time you update your ``webpack.config.js`` file. + +Actually, to use ``enableSassLoader()``, you'll need to install a few +more packages. But Encore will tell you *exactly* what you need. + +After running one of these commands, you can now add ``script`` and ``link`` tags +to the new, compiled assets (e.g. ``/build/global.css`` and ``/build/app.js``). +In Symfony, use the ``asset()`` helper: + +.. code-block:: twig + + {# base.html.twig #} + + + + + + + + + + + + +Requiring JavaScript Modules +---------------------------- + +Webpack is module bundler... which means that you can ``require`` +other JavaScript files. First, create a file that exports a function: + +.. code-block:: javascript + + // assets/js/greet.js + module.exports = function(name) { + return `Yo yo ${name} - welcome to Encore!`; + }; + +We'll use jQuery to print this message on the page. Install it via: + +.. code-block:: terminal + + $ yarn add jquery --dev + +Great! Use ``require()`` to import ``jquery`` and ``greet.js``: + +.. code-block:: javascript + + // assets/js/main.js + + // loads the jquery package from node_modules + var $ = require('jquery'); + + // import the function from greet.js (the .js extension is optional) + // ./ (or ../) means to look for a local file + var greet = require('./greet'); + + $(document).ready(function()) { + $('h1').html(greet()); + }); + +That's it! When you build your assets, jQuery and ``greet.js`` will automatically +be added to the output file (``app.js``). For common libraries like jQuery, you +may want also to :doc:`create a shared entry ` for better performance. + +Requiring CSS Files from JavaScript +----------------------------------- + +You can also require CSS files from your JavaScript: + +.. code-block:: javascript + + // assets/js/main.js + // ... + + // a CSS file with the same name as the entry js will be output + require('../css/main.scss'); + +In this case, ``main.js`` is being added to an entry called ``app`` in ``webpack.config.js``: + +.. code-block:: javascript + + Encore + // ... + .addEntry('app', './assets/js/main.js') + +As soon as you require a CSS file, both an ``app.js`` **and** an ``app.css`` file +will be created. You'll need to add a link tag to the ``app.css`` file in your +templates: + +.. code-block:: diff + + + + diff --git a/frontend/encore/sourcemaps.rst b/frontend/encore/sourcemaps.rst new file mode 100644 index 00000000000..d3add04ba8d --- /dev/null +++ b/frontend/encore/sourcemaps.rst @@ -0,0 +1,27 @@ +Enabling Source Maps +==================== + +`Source maps`_ allow browsers to access to 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: + +.. code-block:: javascript + + // webpack.config.js + // ... + + Encore + // ... + + // this is the default behavior... + .enableSourceMaps(!Encore.isProduction()) + // ... but you can override it by passing a boolean value + .enableSourceMaps(true) + ; + +.. _`Source maps`: https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Use_a_source_map diff --git a/frontend/encore/versioning.rst b/frontend/encore/versioning.rst new file mode 100644 index 00000000000..36327df4d98 --- /dev/null +++ b/frontend/encore/versioning.rst @@ -0,0 +1,61 @@ +Asset Versioning +================ + +.. _encore-long-term-caching: + +Tired of deploying and having browser's cache the old version of your assets? +By calling ``enableVersioning()``, each filename will now include a hash that +changes whenever the *contents* of that file change (e.g. ``app.123abc.js`` +instead of ``app.js``). This allows you to use aggressive caching strategies +(e.g. a far future ``Expires``) because, whenever a file change, its hash will change, +invalidating any existing cache: + +.. code-block:: diff + + // webpack.config.js + // ... + + Encore + .setOutputPath('web/build/') + // ... + + .enableVersioning() + +To link to these assets, Encore creates a ``manifest.json`` file with a map to +the new filenames. + +.. _load-manifest-files: + +Loading Assets from the manifest.json File +------------------------------------------ + +Whenever you run Encore, a ``manifest.json`` file is automatically +created in your ``outputPath`` directory: + +.. code-block:: json + + { + "build/app.js": "/build/app.123abc.js", + "build/dashboard.css": "/build/dashboard.a4bf2d.css" + } + +In your app, you need to read this file to dynamically render the correct paths +in your ``script`` and ``link`` tags. If you're using Symfony, just activate the +``json_manifest_file`` versioning strategy in ``config.yml``: + +.. code-block:: yaml + + # app/config/config.yml + framework: + # ... + assets: + # feature is supported in Symfony 3.3 and higher + json_manifest_path: '%kernel.project_dir%/web/build/manifest.json' + +That's it! Just be sure to wrap each path in the Twig ``asset()`` function +like normal: + +.. code-block:: twig + + + + From e0dd2f5a16ca0cb03240d54f0e2f62c0a42c6f60 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 10 Jun 2017 14:29:06 -0400 Subject: [PATCH 2/5] Fixing unindexed docs --- frontend.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frontend.rst b/frontend.rst index 7f1535579a7..e2d6abeb99f 100644 --- a/frontend.rst +++ b/frontend.rst @@ -76,3 +76,8 @@ Full API :glob: frontend/* + +.. toctree:: + :hidden: + + frontend/encore/* From 154def004b5e5c34c9d6f4e5c53d741ab9480a00 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 11 Jun 2017 08:51:34 -0400 Subject: [PATCH 3/5] Tweaks from feedback, including making some lines longer (they were getting a little too short) --- frontend.rst | 27 ++++++++++++------------ frontend/encore/bootstrap.rst | 8 +++---- frontend/encore/cdn.rst | 12 +++++------ frontend/encore/css-preprocessors.rst | 3 +-- frontend/encore/dev-server.rst | 14 ++++++------ frontend/encore/installation.rst | 7 +++--- frontend/encore/page-specific-assets.rst | 6 +++--- frontend/encore/postcss.rst | 3 +-- frontend/encore/reactjs.rst | 3 +-- frontend/encore/server-data.rst | 5 +++-- frontend/encore/simple-example.rst | 10 ++++----- 11 files changed, 47 insertions(+), 51 deletions(-) diff --git a/frontend.rst b/frontend.rst index e2d6abeb99f..c23ba700703 100644 --- a/frontend.rst +++ b/frontend.rst @@ -7,25 +7,24 @@ create static CSS and JS files in your ``web/`` directory and include them in yo templates. Webpack Encore -============== +-------------- -`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. +`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. -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. +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. .. tip:: Encore is made by `Symfony`_ and works *beautifully* in Symfony applications. But it can easily be used in any application... in any language! -Documentation -------------- +Encore Documentation +-------------------- Getting Started ............... @@ -36,16 +35,16 @@ Getting Started Adding more Features .................... -* :doc:`CSS Preprocessors: SASS, LESS, etc ` +* :doc:`CSS Preprocessors: Sass, LESS, etc ` * :doc:`PostCSS and autoprefixing ` * :doc:`Enabling React.js ` * :doc:`Configuring Babel ` -* :doc:`Sourcemaps ` +* :doc:`Source maps ` Optimizing .......... -* :doc:`Versioning and manifest.json ` +* :doc:`Versioning (and the manifest.json file) ` * :doc:`Using A CDN ` * :doc:`Creating a "Shared" entry for re-used modules ` diff --git a/frontend/encore/bootstrap.rst b/frontend/encore/bootstrap.rst index 6f3b5fc0100..2110d007ad9 100644 --- a/frontend/encore/bootstrap.rst +++ b/frontend/encore/bootstrap.rst @@ -9,11 +9,11 @@ First, install it. To be able to customize things further, we'll install $ yarn add bootstrap-sass --dev -Importing Bootstrap SASS +Importing Bootstrap Sass ------------------------ Now that ``bootstrap-sass`` lives in your ``node_modules`` directory, you can -import it from any SASS or JavaScript file. For example, if you're already have +import it from any Sass or JavaScript file. For example, if you're already have a ``global.scss`` file, import it from there: .. code-block:: css @@ -34,7 +34,7 @@ file into ``global.scss``. You can even customize the Bootstrap variables first! If you don't need *all* of Bootstrap's features, you can include specific files in the ``bootstrap`` directory instead - e.g. ``~bootstrap-sass/assets/stylesheets/bootstrap/alerts``. -After including ``bootstrap-sass``, your webpack builds might become slow. To fix +After including ``bootstrap-sass``, your Webpack builds might become slow. To fix this, you can use the ``resolve_url_loader`` option: .. code-block:: diff @@ -47,7 +47,7 @@ this, you can use the ``resolve_url_loader`` option: ; This disables the ``resolve-url-loader`` in Webpack, which means that any -``url()`` paths in your SASS files must now be relative to the original source +``url()`` paths in your Sass files must now be relative to the original source entry file instead of whatever file you're inside of (see `Problems with url()`_). To load Bootstrap, you'll need to override the path to its icons: diff --git a/frontend/encore/cdn.rst b/frontend/encore/cdn.rst index f387f84d758..59512dd8ad7 100644 --- a/frontend/encore/cdn.rst +++ b/frontend/encore/cdn.rst @@ -1,9 +1,9 @@ Using a CDN =========== -Are you deploying to a CDN? That's awesome :) - and configuring -Encore for that is easy. Once you've made sure that your built files -are uploaded to the CDN, configure it in Encore: +Are you deploying to a CDN? That's awesome :) - and configuring Encore for that is +easy. Once you've made sure that your built files are uploaded to the CDN, configure +it in Encore: .. code-block:: diff @@ -36,12 +36,12 @@ e.g. ``https://my-cool-app.com.global.prod.fastly.net/dashboard.js``. directly from your web server. You *do* need to make sure that the ``script`` and ``link`` tags you include on your -pages also uses the CDN. Fortunately, the ``manifest.json`` paths are -updated to point to the CDN. In Symfony, as long as you've configured +pages also uses the CDN. Fortunately, the ``manifest.json`` paths are updated to +point to the CDN. In Symfony, as long as you've configured :doc:`Asset Versioning `, you're done! The ``manifest.json`` file includes the full CDN URL: -.. code-block:: js +.. code-block:: twig {# Your script/link tags don't need to change at all to support the CDN #} diff --git a/frontend/encore/css-preprocessors.rst b/frontend/encore/css-preprocessors.rst index d9baa1c6ea5..8c26d6e94a3 100644 --- a/frontend/encore/css-preprocessors.rst +++ b/frontend/encore/css-preprocessors.rst @@ -22,8 +22,7 @@ And enable it in ``webpack.config.js``: .enableSassLoader() ; -That's it! All files ending in ``.sass`` or ``.scss`` will -be processed. +That's it! All files ending in ``.sass`` or ``.scss`` will be processed. Using LESS ---------- diff --git a/frontend/encore/dev-server.rst b/frontend/encore/dev-server.rst index 756cdd6a9d2..83cb79e2065 100644 --- a/frontend/encore/dev-server.rst +++ b/frontend/encore/dev-server.rst @@ -1,22 +1,22 @@ Using webpack-dev-server and HMR ================================ -While developing, instead of using ``encore dev --watch``, you can -instead use the `webpack-dev-server`_: +While developing, instead of using ``encore dev --watch``, you can instead use the +`webpack-dev-server`_: .. code-block:: terminal $ ./node_modules/.bin/encore dev-server -This serves the built assets from a new server at ``http://localhost:8080`` -(it does not actually write any files to disk). This means your -``script`` and ``link`` tags need to change to point to this. +This serves the built assets from a new server at ``http://localhost:8080`` (it does +not actually write any files to disk). This means your ``script`` and ``link`` tags +need to change to point to this. If you've activated the :ref:`manifest.json versioning ` you're done: the paths in your templates will automatically point to the dev server. -You can also pass options to the ``dev-server`` command: any options that -are supported by the normal `webpack-dev-server`_. For example: +You can also pass options to the ``dev-server`` command: any options that are supported +by the normal `webpack-dev-server`_. For example: .. code-block:: terminal diff --git a/frontend/encore/installation.rst b/frontend/encore/installation.rst index 8d9cc283aec..bae06fe840f 100644 --- a/frontend/encore/installation.rst +++ b/frontend/encore/installation.rst @@ -14,10 +14,9 @@ Then, install Encore into your project with yarn: If you want to use `npm`_ instead of `yarn`_, replace ``yarn add xxx --dev`` by ``npm install xxx --save-dev``. -This command creates (or modifies) a ``package.json`` file and downloads -dependencies into a ``node_modules/`` directory. When using Yarn, a file called -``yarn.lock`` is also created/updated. When using npm 5, a ``package-lock.json`` -file is created/updated. +This command creates (or modifies) a ``package.json`` file and downloads dependencies +into a ``node_modules/`` directory. When using Yarn, a file called ``yarn.lock`` +is also created/updated. When using npm 5, a ``package-lock.json`` file is created/updated. .. tip:: diff --git a/frontend/encore/page-specific-assets.rst b/frontend/encore/page-specific-assets.rst index c59a7674db9..a584e73dce6 100644 --- a/frontend/encore/page-specific-assets.rst +++ b/frontend/encore/page-specific-assets.rst @@ -21,9 +21,9 @@ a new ``checkout`` entry: + .addEntry('checkout', './assets/js/checkout.js') ; -Inside ``checkout.js``, add or require the JavaScript and CSS you need. -Then, just include a ``script`` tag for ``checkout.js`` on the checkout -page (and a ``link`` tag for ``checkout.css`` if you import any CSS). +Inside ``checkout.js``, add or require the JavaScript and CSS you need. Then, just +include a ``script`` tag for ``checkout.js`` on the checkout page (and a ``link`` +tag for ``checkout.css`` if you import any CSS). Multiple Entries Per Page? -------------------------- diff --git a/frontend/encore/postcss.rst b/frontend/encore/postcss.rst index 9ad8328346c..12b66fd3078 100644 --- a/frontend/encore/postcss.rst +++ b/frontend/encore/postcss.rst @@ -33,8 +33,7 @@ Then, Enable the loader in Encore! + .enablePostCssLoader() ; -That's it! The ``postcss-loader`` will now be used for all CSS, Sass, etc -files. +That's it! The ``postcss-loader`` will now be used for all CSS, Sass, etc files. .. _`PostCSS`: http://postcss.org/ .. _`autoprefixing`: https://github.com/postcss/autoprefixer diff --git a/frontend/encore/reactjs.rst b/frontend/encore/reactjs.rst index dd2877b0d06..58bd547b851 100644 --- a/frontend/encore/reactjs.rst +++ b/frontend/encore/reactjs.rst @@ -1,8 +1,7 @@ Enabling React.js ================= -Using React? Make sure you have React installed, along with the -`babel-preset-react`_: +Using React? Make sure you have React installed, along with the `babel-preset-react`_: .. code-block:: terminal diff --git a/frontend/encore/server-data.rst b/frontend/encore/server-data.rst index 5c768c24cce..55d5c74bc3a 100644 --- a/frontend/encore/server-data.rst +++ b/frontend/encore/server-data.rst @@ -25,10 +25,11 @@ Fetch this in JavaScript: There is no size limit for the value of the ``data-`` attributes, so you can store any content. In Twig, use the ``html_attr`` escaping strategy to avoid messing -with HTML attributes: +with HTML attributes. For example, if your ``User`` object has some ``getProfileData()`` +method that returns an array, you could: .. code-block:: twig -
+
diff --git a/frontend/encore/simple-example.rst b/frontend/encore/simple-example.rst index a7ee527a18c..2b0bd4c6f5d 100644 --- a/frontend/encore/simple-example.rst +++ b/frontend/encore/simple-example.rst @@ -8,7 +8,7 @@ an ``assets/`` directory: * ``assets/css/global.scss`` With Encore, we can easily minify these files, pre-process ``global.scss`` -through SASS and a *lot* more. +through Sass and a *lot* more. Configuring Encore/Webpack -------------------------- @@ -52,8 +52,8 @@ Inside, use Encore to help generate your Webpack configuration. // export the final configuration module.exports = Encore.getWebpackConfig(); -This is already a rich setup: it outputs 2 files, uses the -SASS pre-processor and enables sourcemaps to help debugging. +This is already a rich setup: it outputs 2 files, uses the Sass pre-processor and +enables source maps to help debugging. .. _encore-build-assets: @@ -99,8 +99,8 @@ In Symfony, use the ``asset()`` helper: Requiring JavaScript Modules ---------------------------- -Webpack is module bundler... which means that you can ``require`` -other JavaScript files. First, create a file that exports a function: +Webpack is module bundler... which means that you can ``require`` other JavaScript +files. First, create a file that exports a function: .. code-block:: javascript From 307fc6eaa91ef8a673f68bfa4c3ce17fb9493ace Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 11 Jun 2017 09:28:08 -0400 Subject: [PATCH 4/5] adding missing glob --- frontend.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend.rst b/frontend.rst index c23ba700703..51b8b9b8d22 100644 --- a/frontend.rst +++ b/frontend.rst @@ -78,5 +78,6 @@ Full API .. toctree:: :hidden: + :glob: frontend/encore/* From a2b7a97aaa0256f97533a50f520107b3322d05a7 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 12 Jun 2017 10:58:56 -0400 Subject: [PATCH 5/5] fixing library name --- frontend/encore/simple-example.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/encore/simple-example.rst b/frontend/encore/simple-example.rst index 2b0bd4c6f5d..65ee0891107 100644 --- a/frontend/encore/simple-example.rst +++ b/frontend/encore/simple-example.rst @@ -19,7 +19,7 @@ Inside, use Encore to help generate your Webpack configuration. .. code-block:: javascript // webpack.config.js - var Encore = require('@weaverryan/webpack-remix'); + var Encore = require('@symfony/webpack-encore'); Encore // directory where should all compiled assets will be stored