diff --git a/frontend.rst b/frontend.rst index 873153b07b6..f19aeaa08ec 100644 --- a/frontend.rst +++ b/frontend.rst @@ -48,6 +48,7 @@ Adding more Features * :doc:`PostCSS and autoprefixing ` * :doc:`Enabling React.js ` * :doc:`Enabling Vue.js (vue-loader) ` +* :doc:`/frontend/encore/copy-files` * :doc:`Configuring Babel ` * :doc:`Source maps ` * :doc:`Enabling TypeScript (ts-loader) ` @@ -55,8 +56,10 @@ Adding more Features Optimizing .......... -* :doc:`Versioning (and the manifest.json file) ` +* :doc:`Versioning (and the entrypoints.json/manifest.json files) ` * :doc:`Using a CDN ` +* :doc:`/frontend/encore/code-splitting` +* :doc:`/frontend/encore/split-chunks` * :doc:`Creating a "Shared" entry for re-used modules ` * :doc:`/frontend/encore/url-loader` diff --git a/frontend/encore/babel.rst b/frontend/encore/babel.rst index 1a060c950d1..2affea43c5f 100644 --- a/frontend/encore/babel.rst +++ b/frontend/encore/babel.rst @@ -2,8 +2,8 @@ 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). +``babel-loader`` with sensible defaults (e.g. with the ``@babel/preset-env`` and +``@babel/preset-react`` if requested). Need to extend the Babel configuration further? The easiest way is via ``configureBabel()``: @@ -16,17 +16,37 @@ Need to extend the Babel configuration further? The easiest way is via Encore // ... - // first, install any presets you want to use (e.g. yarn add babel-preset-es2017) - // then, modify the default Babel configuration .configureBabel(function(babelConfig) { // add additional presets - babelConfig.presets.push('es2017'); + // babelConfig.presets.push('@babel/preset-flow'); // no plugins are added by default, but you can add some // babelConfig.plugins.push('styled-jsx/babel'); + }, { + // node_modules is not processed through Babel by default + // but you can whitelist specific modules to process + // include_node_modules: ['foundation-sites'] + + // or completely control the exclude + // exclude: /bower_components/ }) ; +Configuring Browser Targets +--------------------------- + +The ``@babel/preset-env`` preset rewrites your JavaScript so that the final syntax +will work in whatever browsers you want. To configure the browsers that you need +to support, see :ref:`browserslist_package_config`. + +After change our "browerslist" config, you will need to manually remove the babel +cache directory: + +.. code-block:: terminal + + $ On Unix run this command. On Windows, clear this directory manually + $ rm -rf node_modules/.cache/babel-loader/ + Creating a .babelrc File ------------------------ @@ -37,21 +57,7 @@ Babel, but it has a downside: as soon as a ``.babelrc`` file is present, if you call ``Encore.enableReactPreset()``, the ``react`` preset will *not* automatically be added to Babel: you must add it yourself in ``.babelrc``. -An example ``.babelrc`` file might look like this: - -.. code-block:: json - - { - presets: [ - ['env', { - modules: false, - targets: { - browsers: '> 1%', - uglify: true - }, - useBuiltIns: true - }] - ] - } +As soon as a ``.babelrc`` file is present, it will take priority over the Babel +configuration added by Encore. .. _`Babel`: http://babeljs.io/ diff --git a/frontend/encore/bootstrap.rst b/frontend/encore/bootstrap.rst index 87f25ec662a..ff281f588ac 100644 --- a/frontend/encore/bootstrap.rst +++ b/frontend/encore/bootstrap.rst @@ -41,29 +41,17 @@ Bootstrap JavaScript requires jQuery and Popper.js, so make sure you have this i .. code-block:: terminal - $ yarn add jquery --dev - $ yarn add popper.js --dev + $ yarn add jquery popper.js --dev -Next, make sure to 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: +Now, require bootstrap from any of your JavaScript files: .. code-block:: javascript // app.js const $ = require('jquery'); - // JS is equivalent to the normal "bootstrap" package - // no need to set this to a variable, just require it + // this "modifies" the jquery module: adding behavior to it + // the bootstrap module doesn't export/return anything require('bootstrap'); // or you can include specific pieces @@ -74,8 +62,13 @@ variable. Now, require bootstrap from any of your JavaScript files: $('[data-toggle="popover"]').popover(); }); -Thanks to ``autoProvidejQuery()``, you can require any other jQuery -plugins in a similar way: +Using other Bootstrap / jQuery Plugins +-------------------------------------- + +If you need to use jQuery plugins that work well with jQuery, you may need to use +Encore's :ref:`autoProvidejQuery() ` method so that +these plugins know where to find jQuery. Then, you can include the needed JavaScript +and CSS like normal: .. code-block:: javascript diff --git a/frontend/encore/cdn.rst b/frontend/encore/cdn.rst index 90650f285ad..f1bfddfcc48 100644 --- a/frontend/encore/cdn.rst +++ b/frontend/encore/cdn.rst @@ -36,12 +36,6 @@ 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 use 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:: twig - - {# Your script/link tags don't need to change at all to support the CDN #} - +pages also use the CDN. Fortunately, the +:ref:`entrypoints.json ` paths are updated +to include the full URL to the CDN. diff --git a/frontend/encore/code-splitting.rst b/frontend/encore/code-splitting.rst new file mode 100644 index 00000000000..beab201f4f9 --- /dev/null +++ b/frontend/encore/code-splitting.rst @@ -0,0 +1,64 @@ +Async Code Splitting +==================== + +When you require/import a JavaScript or CSS module, Webpack compiles that code into +the final JavaScript or CSS file. Usually, that's exactly what you want. But what +if you only need to use a piece of code under certain conditions? For example, +what if you want to use `video.js`_ to play a video, but only once a user has +clicked a link: + +.. code-block:: javascript + + // assets/js/app.js + + import $ from 'jquery'; + // a fictional "large" module (e.g. it imports video.js internally) + import VideoPlayer from './components/VideoPlayer'; + + $('.js-open-video').on('click', function() { + // use the larger VideoPlayer module + const player = new VideoPlayer('some-element'); + }); + +In this example, the VidePlayer module and everything it imports will be packaged +into the final, built JavaScript file, even though it may not be very common for +someone to actually need it. A better solution is to use `dynamic imports`_: load +the code via AJAX when it's needed: + +.. code-block:: javascript + + // assets/js/app.js + + import $ from 'jquery'; + + $('.js-open-video').on('click', function() { + // you could start a loading animation here + + // use import() as a function - it returns a Promise + import('./components/VideoPlayer').then(({ default: VideoPlayer }) => { + // you could stop a loading animation here + + // use the larger VideoPlayer module + const player = new VideoPlayer('some-element'); + + }).catch(error => 'An error occurred while loading the component'); + }); + +By using ``import()`` like a function, the module will be downloaded async and +the ``.then()`` callback will be executed when it's finished. The ``VideoPlayer`` +argument to the callback will be the loaded module. In other words, it works like +normal AJAX calls! Behind the scenes, Webpack will package the ``VideoPlayer`` module +into a separate file (e.g. ``0.js``) so it can be downloaded. All the details are +handled for you. + +The ``{ default: VideoPlayer }`` part may look strange. When using the async +import, your ``.then()`` callback is passed an object, where the *actual* module +is on a ``.default`` key. There are reasons why this is done, but it does look +quirky. The ``{ default: VideoPlayer }`` code makes sure that the ``VideoPlayer`` +module we want is read from this ``.default`` property. + +For more details and configuration options, see `dynamic imports`_ on Webpack's +documentation. + +.. _`video.js`: https://videojs.com/ +.. _`dynamic imports`: https://webpack.js.org/guides/code-splitting/#dynamic-imports diff --git a/frontend/encore/copy-files.rst b/frontend/encore/copy-files.rst new file mode 100644 index 00000000000..270b3276af2 --- /dev/null +++ b/frontend/encore/copy-files.rst @@ -0,0 +1,66 @@ +Copying & Referencing Images +============================ + +Need to reference a static file - like the path to an image for an ``img`` tag? +That can be tricky if you store your assets outside of the public document root. +Fortunately, depending on your situation, there is a solution! + +Referencing Images from Inside a Webpacked JavaScript File +---------------------------------------------------------- + +To reference an image tag from inside a JavaScript file, *require* the file: + +.. code-block:: javascript + + // assets/js/app.js + + // returns the final, public path to this file + // path is relative to this file - e.g. assets/images/logo.png + const logoPath = require('../images/logo.png'); + + var html = ``; + +When you ``require`` (or ``import``) an image file, Webpack copies it into your +output directory and returns the final, *public* path to that file. + +Referencing Image files from a Template +--------------------------------------- + +To reference an image file from outside of a JavaScript file that's processed by +Webpack - like a template - you can use the ``copyFiles()`` method to copy those +files into your final output directory. + +.. code-block:: diff + + // webpack.config.js + + Encore + // ... + .setOutputPath('web/build/') + + + .copyFiles({ + + from: './assets/images', + + + + // optional target path, relative to the output dir + + //to: 'images/[path][name].[ext]', + + + + // only copy files matching this pattern + + //pattern: /\.(png|jpg|jpeg)$/ + + }) + +This will copy all files from ``assets/images`` into ``web/build`` (the output +path). If you have :doc:`versioning enabled `, the copied files will +include a hash based on their content. + +To render inside Twig, use the ``asset()`` function: + + {# assets/images/logo.png was copied to web/build/logo.png #} + ` option, +which tells the ``asset()`` function to read the final paths from the ``manifest.json`` +file. If you're not sure what path argument to pass to the ``asset()`` function, +find the file in ``manifest.json`` and use the *key* as the argument. diff --git a/frontend/encore/css-preprocessors.rst b/frontend/encore/css-preprocessors.rst index 540e613b106..6b70e8f38cb 100644 --- a/frontend/encore/css-preprocessors.rst +++ b/frontend/encore/css-preprocessors.rst @@ -1,29 +1,7 @@ -CSS Preprocessors: Sass, LESS, etc. -=================================== +CSS Preprocessors: Sass, LESS, Stylus, 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 pre-processed. You -can also pass options to ``sass-loader``: +To use the Sass, LESS or Stylus pre-processors, enable the one you want in ``webpack.config.js``: .. code-block:: javascript @@ -32,46 +10,24 @@ can also pass options to ``sass-loader``: Encore // ... - .enableSassLoader(function(options) { - // https://github.com/sass/node-sass#options - // options.includePaths = [...] - }); - ; - -Using LESS ----------- - -To use the LESS pre-processor, install the dependencies: -.. code-block:: terminal + // enable just the one you want - $ yarn add --dev less-loader less - -And enable it in ``webpack.config.js``: - -.. code-block:: javascript - - // webpack.config.js - // ... + // processes files ending in .scss or .sass + .enableSassLoader() - Encore - // ... + // processes files ending in .less .enableLessLoader() - ; -That's it! All files ending in ``.less`` will be pre-processed. You can also pass -options to ``less-loader``: + // processes files ending in .styl + .enableStylusLoader() + ; -.. code-block:: javascript +Then restart Encore. When you do, it will give you a command you can run to +install any missing dependencies. After running that command and restarting +Encore, you're done! - // webpack.config.js - // ... +You can also pass configuration options to each of the loaders. See the +`Encore's index.js file`_ for detailed documentation. - Encore - // ... - .enableLessLoader(function(options) { - // https://github.com/webpack-contrib/less-loader#examples - // http://lesscss.org/usage/#command-line-usage-options - // options.relativeUrls = false; - }); - ; +.. _`Encore's index.js file`: https://github.com/symfony/webpack-encore/blob/master/index.js diff --git a/frontend/encore/dev-server.rst b/frontend/encore/dev-server.rst index f092faf7cce..6fce0012d8f 100644 --- a/frontend/encore/dev-server.rst +++ b/frontend/encore/dev-server.rst @@ -1,26 +1,28 @@ Using webpack-dev-server and HMR ================================ -While developing, instead of using ``encore dev --watch``, you can use the +While developing, instead of using ``yarn encore dev --watch``, you can use the `webpack-dev-server`_: .. code-block:: terminal - $ ./node_modules/.bin/encore dev-server + $ yarn 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. +If you're using the ``encore_entry_script_tags()`` and ``encore_entry_link_tags()`` +Twig shortcuts (or are :ref:`processing your assets through entrypoints.json ` +in some other way), 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 + $ yarn encore dev-server --https --port 9000 This will start a server at ``https://localhost:9000``. diff --git a/frontend/encore/faq.rst b/frontend/encore/faq.rst index d0fb6f4a6e7..11348c5567d 100644 --- a/frontend/encore/faq.rst +++ b/frontend/encore/faq.rst @@ -74,20 +74,15 @@ like ``/myAppSubdir``), you just need to configure that when calling ``Encore.se + .setPublicPath('/myAppSubdir/build') + // this is now needed so that your manifest.json keys are still `build/foo.js` - + // i.e. you won't need to change anything in your Symfony app + + // (which is a file that's used by Symfony's asset function) + .setManifestKeyPrefix('build') ; -If you're :ref:`processing your assets through manifest.json `, -you're done! The ``manifest.json`` file will now include the subdirectory in the -final paths: - -.. code-block:: json - - { - "build/app.js": "/myAppSubdir/build/app.123abc.js", - "build/dashboard.css": "/myAppSubdir/build/dashboard.a4bf2d.css" - } +If you're using the ``encore_entry_script_tags()`` and ``encore_entry_link_tags()`` +Twig shortcuts (or are :ref:`processing your assets through entrypoints.json ` +in some other way) you're done! These shortcut methods read from an +:ref:`entrypoints.json ` file that will +now contain the subdirectory. "jQuery is not defined" or "$ is not defined" --------------------------------------------- @@ -102,9 +97,10 @@ code that you're using. See :doc:`/frontend/encore/legacy-apps` for the fix. Uncaught ReferenceError: webpackJsonp is not defined ---------------------------------------------------- -If you get this error, it's probably because you've just added a :doc:`shared entry ` -but you *forgot* to add a ``script`` tag for the new ``manifest.js`` file. See the -information about the :ref:`script tags ` in that section. +If you get this error, it's probably because you've forgotten to add a ``script`` +tag for the ``runtime.js`` file that contains Webpack's runtime. If you're using +the ``encore_entry_script_tags()`` Twig function, this should never happen: the +file script tag is rendered automatically. This dependency was not found: some-module in ./path/to/file.js --------------------------------------------------------------- @@ -133,4 +129,11 @@ this via: // require a non-minified file whenever possible require('respond.js/dest/respond.src.js'); +I need to execute Babel on a third-party Module +----------------------------------------------- + +For performance, Encore does not process libraries inside ``node_modules/`` through +Babel. But, you can change that via the ``configureBabel()`` method. See +:doc:`/frontend/encore/babel` for details. + .. _`rsync`: https://rsync.samba.org/ diff --git a/frontend/encore/installation-no-flex.rst b/frontend/encore/installation-no-flex.rst index 589a70891d3..9d30b3a44a0 100644 --- a/frontend/encore/installation-no-flex.rst +++ b/frontend/encore/installation-no-flex.rst @@ -58,6 +58,10 @@ Next, create a new ``webpack.config.js`` file at the root of your project: //.addEntry('page1', './assets/js/page1.js') //.addEntry('page2', './assets/js/page2.js') + // will require an extra script tag for runtime.js + // but, you probably want this, unless you're building a single-page app + .enableSingleRuntimeChunk() + .cleanupOutputBeforeBuild() .enableSourceMaps(!Encore.isProduction()) // enables hashed filenames (e.g. app.abc123.css) @@ -97,4 +101,13 @@ And the new ``assets/css/app.css`` file: You'll customize and learn more about these file in :doc:`/frontend/encore/simple-example`. +.. caution:: + + Some of the documentation will use features that are specific to Symfony or + Symfony's `WebpackEncoreBundle`_. These are optional, and are special ways of + pointing to the asset paths generated by Encore that enable features like + :doc:`versioning ` and + :doc:`split chunks `. + .. _`npm`: https://www.npmjs.com/ +.. _WebpackEncoreBundle: https://github.com/symfony/webpack-encore-bundle diff --git a/frontend/encore/installation.rst b/frontend/encore/installation.rst index 959c8b253a9..4061691153b 100644 --- a/frontend/encore/installation.rst +++ b/frontend/encore/installation.rst @@ -10,7 +10,7 @@ run: .. code-block:: terminal - $ composer require symfony/webpack-encore-pack + $ composer require encore $ yarn install This will create a ``webpack.config.js`` file, add the ``assets/`` directory, and diff --git a/frontend/encore/legacy-apps.rst b/frontend/encore/legacy-apps.rst index d9ccb764bcc..4f1193d7e06 100644 --- a/frontend/encore/legacy-apps.rst +++ b/frontend/encore/legacy-apps.rst @@ -1,5 +1,5 @@ -jQuery and Legacy Applications -============================== +jQuery Plugins and Legacy Applications +====================================== Inside Webpack, when you require a module, it does *not* (usually) set a global variable. Instead, it just returns a value: @@ -10,30 +10,25 @@ Instead, it just returns a value: 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). - -Using Libraries that Expect jQuery to be Global ------------------------------------------------ - -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 ``$`` or ``jQuery`` global variables. If those variables -are not defined, you'll get these errors: +jQuery to be global *or* if *your* JavaScript isn't being processed through Webpack +(e.g. you have some JavaScript in your templates) and you need jQuery. Both will +cause similar 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. +The fix depends on what code is causing the problem. + +.. _encore-autoprovide-jquery: -So, when working with legacy applications, you may need to add the following to -``webpack.config.js``: +Fixing jQuery Plugins that Expect jQuery to be Global +----------------------------------------------------- + +jQuery plugins often expect that jQuery is already available via the ``$`` or +``jQuery`` global variables. To fix this, call ``autoProvidejQuery()`` from your +``webpack.config.js`` file: .. code-block:: diff @@ -42,6 +37,10 @@ So, when working with legacy applications, you may need to add the following to + .autoProvidejQuery() ; +After restarting Encore, Webpack will look for all uninitialized ``$`` and ``jQuery`` +variables and automatically require ``jquery`` and set those variables for you. +It "rewrites" the "bad" code to be correct. + Internally, this ``autoProvidejQuery()`` method calls the ``autoProvideVariables()`` method from Encore. In practice, it's equivalent to doing: @@ -61,25 +60,27 @@ method from Encore. In practice, it's equivalent to doing: Accessing jQuery from outside of Webpack JavaScript Files --------------------------------------------------------- -If you also need to provide access to ``$`` and ``jQuery`` variables outside of +If *your* code needs access to ``$`` or ``jQuery`` and you are inside of a file +that's processed by Webpack/Encore, you should remove any "$ is not defined" errors +by requiring jQuery: ``var $ = require('jquery')``. + +But if you also need to provide access to ``$`` and ``jQuery`` variables outside of JavaScript files processed by Webpack (e.g. JavaScript that still lives in your templates), you need to manually set these as global variables in some JavaScript file that is loaded before your legacy code. -For example, you could define a ``common.js`` file that's processed by Webpack and -loaded on every page with the following content: +For example, in your ``app.js`` file that's processed by Webpack and loaded on every +page, add: -.. code-block:: javascript +.. code-block:: diff // require jQuery normally const $ = require('jquery'); - // create global $ and jQuery variables - global.$ = global.jQuery = $; - -.. tip:: + + // create global $ and jQuery variables + + global.$ = global.jQuery = $; - The ``global`` variable is a special way of setting things in the ``window`` - variable. In a web context, using ``global`` and ``window`` are equivalent, - except that ``window.jQuery`` won't work when using ``autoProvidejQuery()``. - In other words, use ``global``. +The ``global`` variable is a special way of setting things in the ``window`` +variable. In a web context, using ``global`` and ``window`` are equivalent, +except that ``window.jQuery`` won't work when using ``autoProvidejQuery()``. +In other words, use ``global``. diff --git a/frontend/encore/page-specific-assets.rst b/frontend/encore/page-specific-assets.rst index a932de5da5d..92ab00a0a61 100644 --- a/frontend/encore/page-specific-assets.rst +++ b/frontend/encore/page-specific-assets.rst @@ -5,41 +5,23 @@ If you're creating a single page app (SPA), then you probably only need to defin *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/app.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). +To learn how to set this up, see the :ref:`multiple-javascript-entries` example. Multiple Entries Per Page? -------------------------- -Typically, you should include only *one* JavaScript entry 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. +Typically, you should include only *one* JavaScript entry per page. 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. +However, it's pretty common to need to include some global JavaScript and CSS on +every page. For that reason, it usually makes sense to have one entry (e.g. ``app``) +that contains this global code (both JavaScript & CSS) and is included on every +page (i.e. it's included in the *layout* of your app). This means that you will +always have one, global entry on every page (e.g. ``app``) and you *may* have one +page-specific JavaScript and CSS file from a page-specific entry (e.g. ``checkout``). .. tip:: - Be sure to create a :doc:`shared entry ` to avoid duplicating - the Webpack bootstrap logic and any shared modules. + Be sure to use :doc:`split chunks ` + to avoid duplicating and shared code between your entry files. diff --git a/frontend/encore/postcss.rst b/frontend/encore/postcss.rst index 4b0e76d5321..9da106653db 100644 --- a/frontend/encore/postcss.rst +++ b/frontend/encore/postcss.rst @@ -35,6 +35,8 @@ Then, Enable the loader in Encore! + .enablePostCssLoader() ; +Because you just modified ``webpack.config.js``, stop and restart Encore. + That's it! The ``postcss-loader`` will now be used for all CSS, Sass, etc files. You can also pass options to the `postcss-loader`_ by passing a callback: @@ -51,6 +53,8 @@ You can also pass options to the `postcss-loader`_ by passing a callback: + }) ; +.. _browserslist_package_config: + Adding browserslist to package.json ----------------------------------- @@ -61,17 +65,16 @@ support. The best-practice is to configure this directly in your ``package.json` .. code-block:: diff { - + "browserslist": [ "last 2 versions", "ios >= 8" ] + + "browserslist": [ + + "> 0.5%", + + "last 2 versions", + + "Firefox ESR", + + "not dead" + + ] } See `browserslist`_ for more details on the syntax. -.. note:: - - Encore uses `babel-preset-env`_, which *also* needs to know which browsers you - want to support. But this does *not* read the ``browserslist`` config key. You - must configure the browsers separately via :doc:`configureBabel() `. - .. _`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 index 58bd547b851..f5e216cb26e 100644 --- a/frontend/encore/reactjs.rst +++ b/frontend/encore/reactjs.rst @@ -1,25 +1,23 @@ Enabling React.js ================= -Using React? Make sure you have React installed, along with the `babel-preset-react`_: +Using React? First enable support for it in ``webpack.config.js``: -.. code-block:: terminal - - $ yarn add --dev react react-dom prop-types babel-preset-react - -Enable react in your ``webpack.config.js``: - -.. code-block:: javascript +.. code-block:: diff // webpack.config.js // ... Encore // ... - .enableReactPreset() + + .enableReactPreset() ; -That's it! Your ``.js`` and ``.jsx`` files will now be transformed through -``babel-preset-react``. + +Then restart Encore. When you do, it will give you a command you can run to +install any missing dependencies. After running that command and restarting +Encore, you're done! + +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 index 8ee87d7ec9c..ae19c262e86 100644 --- a/frontend/encore/server-data.rst +++ b/frontend/encore/server-data.rst @@ -19,6 +19,9 @@ Fetch this in JavaScript: document.addEventListener('DOMContentLoaded', function() { var userRating = document.querySelector('.js-user-rating'); var isAuthenticated = userRating.dataset.isAuthenticated; + + // or with jQuery + //var isAuthenticated = $('.js-user-rating').data('isAuthenticated'); }); .. note:: diff --git a/frontend/encore/shared-entry.rst b/frontend/encore/shared-entry.rst index e4e56e1f599..303b3ee5d06 100644 --- a/frontend/encore/shared-entry.rst +++ b/frontend/encore/shared-entry.rst @@ -1,6 +1,11 @@ Creating a Shared Commons Entry =============================== +.. caution:: + + While this method still works, see :doc:`/frontend/encore/split-chunks` for + the preferred solution to sharing assets between multiple entry files. + 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. To solve this, you can *extract* the common libraries to a "shared" entry file @@ -19,33 +24,13 @@ Update your code to use ``createSharedEntry()``: .addEntry('blog', './assets/js/blog.js') .addEntry('store', './assets/js/store.js') -As soon as you make this change, you need to include *one* extra JavaScript file -in your layout, *before* ``app.js``: - -.. _encore-shared-entry-script: - -.. code-block:: twig - - {# templates/base.html.twig #} - - - - - - - - - - Before making this change, if both ``app.js`` and ``store.js`` require ``jquery``, then ``jquery`` would be packaged into *both* files, which is wasteful. By making ``app.js`` your "shared" entry, *any* code required by ``app.js`` (like jQuery) will *no longer* be packaged into any other files. The same is true for any CSS. Because ``app.js`` contains all the common code that other entry files depend on, -it's obvious that its script (and link) tag must be on every page. The other file -(``manifest.js``) is less obvious: it's needed so that Webpack knows how to load -these shared modules. +it's obvious that its script (and link) tag must be on every page. .. tip:: diff --git a/frontend/encore/simple-example.rst b/frontend/encore/simple-example.rst index cb5308dab1d..9e19bf85ffa 100644 --- a/frontend/encore/simple-example.rst +++ b/frontend/encore/simple-example.rst @@ -7,8 +7,8 @@ CSS and one JS file, organized into an ``assets/`` directory: * ``assets/js/app.js`` * ``assets/css/app.css`` -With Encore, think of your ``app.js`` file as a standalone JavaScript -application: it will *require* all of the dependencies it needs (e.g. jQuery), +With Encore, think of your ``app.js`` file like a standalone JavaScript +application: it will *require* all of the dependencies it needs (e.g. jQuery or React), *including* any CSS. Your ``app.js`` file is already doing this with a special ``require`` function: @@ -17,16 +17,14 @@ application: it will *require* all of the dependencies it needs (e.g. jQuery), // assets/js/app.js // ... - // var $ = require('jquery'); - require('../css/app.css'); - // ... the rest of your JavaScript... + // var $ = require('jquery'); -Encore's job is simple: to read *all* of ``require`` statements and create one -final ``app.js`` (and ``app.css``) that contain *everything* your app needs. Of -course, Encore can do a lot more: minify files, pre-process Sass/LESS, support -React, Vue.js and a *lot* more. +Encore's job (via Webpack) is simple: to read and follow *all* of the ``require`` +statements and create one final ``app.js`` (and ``app.css``) that contains *everything* +your app needs. Of course, Encore can do a lot more: minify files, pre-process Sass/LESS, +support React, Vue.js, etc. Configuring Encore/Webpack -------------------------- @@ -76,9 +74,14 @@ To build the assets, run: Stop and restart ``encore`` each time you update your ``webpack.config.js`` file. -Congrats! You now have two new files! Next, add a ``script`` and ``link`` tag -to the new, compiled assets (e.g. ``/build/app.css`` and ``/build/app.js``) to -your layout. In Symfony, use the ``asset()`` helper: +Congrats! You now have three new files: + +* ``web/build/app.js`` (holds all the JavaScript for your "app" entry) +* ``web/build/app.css`` (holds all the CSS for your "app" entry) +* ``web/build/runtime.js`` (a file that helps Webpack do its job) + +Next, include these in your base layout file. Two Twig helpers from WebpackEncoreBundle +can do most of the work for you: .. code-block:: twig @@ -87,14 +90,51 @@ your layout. In Symfony, use the ``asset()`` helper: - + + {% block stylesheets %} + {# 'app' must match the first argument to addEntry() in webpack.config.js #} + {{ encore_entry_link_tags('app') }} + + + {% endblock %} - + + {% block javascripts %} + {{ encore_entry_script_tags('app') }} + + + {% endblock %} +.. _encore-entrypointsjson-simple-description: + +That's it! When you refresh your page, all of the JavaScript from +``assets/js/app.js`` - as well as any other JavaScript files it included - will +be executed. All the CSS files that were required will also be displayed. + +The ``encore_entry_link_tags()`` and ``encore_entry_script_tags()`` functions +read from an ``entrypoints.json`` file that's generated by Encore to know the exact +filename(s) to render . This file is *especially* useful because you can +:doc:`enable versioning` or +:doc:`point assets to a CDN` without making *any* changes to your +template: the paths in ``entrypoints.json`` will always be the final, correct paths. + +If you're *not* using Symfony, you can ignore the ``entrypoints.json`` file and +point to the final, built file directly. ``entrypoints.json`` is only required for +some optional features. + +.. versionadded:: 0.21.0 + + The ``encore_entry_link_tags()`` comes from WebpackEncoreBundle and relies + on a feature in Encore that was first introduced in version 0.21.0. Previously, + the ``asset()`` function was used to point directly to the file. + Requiring JavaScript Modules ---------------------------- @@ -116,30 +156,32 @@ We'll use jQuery to print this message on the page. Install it via: Great! Use ``require()`` to import ``jquery`` and ``greet.js``: -.. code-block:: javascript +.. code-block:: diff // assets/js/app.js + // ... - // loads the jquery package from node_modules - var $ = require('jquery'); + + // 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'); + + // 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() { - $('body').prepend('

'+greet('john')+'

'); - }); + + $(document).ready(function() { + + $('body').prepend('

'+greet('jill')+'

'); + + }); -That's it! When you build your assets, jQuery and ``greet.js`` will automatically -be added to the output file (``app.js``). +That's it! If you previously ran ``encore dev --watch``, your final, built files +have already been updated: jQuery and ``greet.js`` have been automatically +added to the output file (``app.js``). Refresh to see the message! The import and export Statements -------------------------------- Instead of using ``require`` and ``module.exports`` like shown above, JavaScript has an alternate syntax, which is a more accepted standard. Choose whichever you -want: they function identically: +want: they do the same thing. To export values, use ``exports``: @@ -156,11 +198,14 @@ To import values, use ``import``: .. code-block:: diff // assets/js/app.js + - require('../css/app.css'); + + import '../css/app.css'; + - var $ = require('jquery'); + import $ from 'jquery'; - - require('../css/app.css'); - + import '../css/app.css'; + - var greet = require('./greet'); + + import greet from './greet'; .. _multiple-javascript-entries: @@ -169,45 +214,79 @@ Page-Specific JavaScript or CSS (Multiple Entries) So far, you only have one final JavaScript file: ``app.js``. For simple apps or SPA's (Single Page Applications), that might be fine! However, as your app grows, -you may want to have page-specific JavaScript or CSS (e.g. homepage, blog, store, -etc.). To handle this, add a new "entry" for each page that needs custom JavaScript -or CSS: +you may want to have page-specific JavaScript or CSS (e.g. checkout, account, +etc.). To handle this, create a new "entry" JavaScript file for each page: + +.. code-block:: javascript + + // assets/js/checkout.js + // custom code for your checkout page + +.. code-block:: javascript + + // assets/js/account.js + // custom code for your account page + +Next, use ``addEntry()`` to tell Webpack to read these two new files when it builds: .. code-block:: diff + // webpack.config.js Encore // ... .addEntry('app', './assets/js/app.js') - + .addEntry('homepage', './assets/js/homepage.js') - + .addEntry('blog', './assets/js/blog.js') - + .addEntry('store', './assets/js/store.js') + + .addEntry('checkout', './assets/js/checkout.js') + + .addEntry('account', './assets/js/account.js') // ... -Encore will now render new ``homepage.js``, ``blog.js`` and ``store.js`` files. -Add a ``script`` tag to each of these only on the page where they are needed. +And because you just changed the ``webpack.config.js`` file, make sure to stop +and restart Encore: + +.. code-block:: terminal + + $ yarn run encore dev --watch + +Webpack will now output a new ``checkout.js`` file and a new ``account.js`` file +in your build directory. And, if any of those files require/import CSS, Webpack +will *also* output ``checkout.css`` and ``account.css`` files. + +Finally, include the ``script`` and ``link`` tags on the individual pages where +you need them: + +.. code-block:: diff -.. tip:: + {# templates/.../checkout.html.twig #} + {% extends 'base.html.twig' %} - Remember to restart Encore each time you update your ``webpack.config.js`` file. + + {% block stylesheets %} + + {{ parent() }} + + {{ encore_entry_link_tags('checkout') }} + + {% endblock %} -If any entry requires CSS/Sass files (e.g. ``homepage.js`` requires -``assets/css/homepage.scss``), a CSS file will *also* be output (e.g. ``build/homepage.css``). -Add a ``link`` to the page where that CSS is needed. + + {% block javascripts %} + + {{ parent() }} + + {{ encore_entry_script_tags('checkout') }} + + {% endblock %} -To avoid duplicating the same code in different entry files, see -:doc:`create a shared entry `. +Now, the checkout page will contain all the JavaScript and CSS for the ``app`` entry +(because this is included in ``base.html.twig``) *and* your ``checkout`` entry. -Using Sass ----------- +See :doc:`/frontend/encore/page-specific-assets` for more details. To avoid duplicating +the same code in different entry files, see :doc:`/frontend/encore/split-chunks`. -Instead of using plain CSS you can also use Sass. To use Sass, rename -the ``app.css`` file to ``app.scss``. Update the ``require`` statement: +Using Sass/LESS/Stylus +---------------------- + +You've already mastered the basics of Encore. Nice! But, there are *many* more +features that you can opt into if you need them. For example, instead of using plain +CSS you can also use Sass, LESS or Stylus. To use Sass, rename the ``app.css`` +file to ``app.scss`` and update the ``import`` statement: .. code-block:: diff // assets/js/app.js - - require('../css/app.css'); - + require('../css/app.scss'); + - import '../css/app.css'; + + import '../css/app.scss'; Then, tell Encore to enable the Sass pre-processor: @@ -220,17 +299,33 @@ Then, tell Encore to enable the Sass pre-processor: + .enableSassLoader() ; -Using ``enableSassLoader()`` requires to install additional packages, but Encore -will tell you *exactly* which ones when running it. Encore also supports -LESS and Stylus. See :doc:`/frontend/encore/css-preprocessors`. +Because you just changed your ``webpack.config.js`` file, you'll need to restart +Encore. When you do, you'll see an error! + +> Error: Install sass-loader & node-sass to use enableSassLoader() +> yarn add sass-loader@^7.0.1 node-sass --dev + +Encore supports many features. But, instead of forcing all of them on you, when +you need a feature, Encore will tell you what you need to install. Run: + +.. code-block:: terminal + + $ yarn add sass-loader@^7.0.1 node-sass --dev + $ yarn encore dev --watch + +Your app now supports Sass. Encore also supports LESS and Stylus. See +:doc:`/frontend/encore/css-preprocessors`. Compiling Only a CSS File ------------------------- -To compile CSS together, you should generally follow the pattern above: use ``addEntry()`` -to point to a JavaScript file, then require the CSS needed from inside of that. -However, *if* you want to only compile a CSS file, that's also possible via -``addStyleEntry()``: +.. caution:: + + Using ``addStyleEntry()`` is supported, but not recommended. A better option + is to use follow the pattern above: use ``addEntry()`` to point to a JavaScript + file, then require the CSS needed from inside of that. + +If you want to only compile a CSS file, that's possible via ``addStyleEntry()``: .. code-block:: javascript @@ -246,4 +341,7 @@ This will output a new ``some_page.css``. Keep Going! ----------- -Go back to the :ref:`List of Encore Articles ` to learn more and add new features. +Encore support many more features! For a full list of what you can do, see +`Encore's index.js file`_. Or, go back to :ref:`list of Encore articles `. + +.. _`Encore's index.js file`: https://github.com/symfony/webpack-encore/blob/master/index.js diff --git a/frontend/encore/sourcemaps.rst b/frontend/encore/sourcemaps.rst index 237898d7b65..e46151a5e7f 100644 --- a/frontend/encore/sourcemaps.rst +++ b/frontend/encore/sourcemaps.rst @@ -6,9 +6,7 @@ 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: +Encore's default ``webpack.config.js`` file enables sourcemaps in the ``dev`` build: .. code-block:: javascript @@ -18,10 +16,7 @@ method: 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/split-chunks.rst b/frontend/encore/split-chunks.rst new file mode 100644 index 00000000000..4d7186b4d0a --- /dev/null +++ b/frontend/encore/split-chunks.rst @@ -0,0 +1,66 @@ +Preventing Duplication by "Splitting" Shared Code into Separate Files +===================================================================== + +Suppose you have multiple entry files and *each* requires ``jquery``. In this +case, *each* output file will contain jQuery, making your files much larger than +necessary. To solve this, you can ask webpack to analyze your files and *split* them +into additional files, which will contain "shared" code. + +To enable this, call ``splitEntryChunks()``: + +.. code-block:: diff + + Encore + // ... + + // multiple entry files, which probably import the same code + .addEntry('app', './assets/js/app.js') + .addEntry('homepage', './assets/js/homepage.js') + .addEntry('blog', './assets/js/blog.js') + .addEntry('store', './assets/js/store.js') + + + .splitEntryChunks() + + +Now, each output file (e.g. ``homepage.js``) *may* be split into multiple file +(e.g. ``homepage.js``, ``vendor~homepage.js``). This means that you *may* need to +include *multiple* ``script`` tags (or ``link`` tags for CSS) in your template. +Encore creates an :ref:`entrypoints.json ` +file that lists exactly which CSS and JavaScript files are needed for each entry. + +If you're using the ``encore_entry_link_tags()`` and ``encore_entry_script_tags()`` +Twig functions from WebpackEncoreBundle, you don't need to do anything else! These +functions automatically read this file and render as many ``script`` or ``link`` +tags as needed: + +.. code-block:: twig + + {# + May now render multiple script tags: + + + + #} + {{ encore_entry_script_tags('homepage') }} + +Controlling how Assets are Split +-------------------------------- + +The logic for *when* and *how* to split the files is controlled by the +`SplitChunksPlugin from Webpack`_. You can control the configuration passed to +this plugin with the ``configureSplitChunks()`` function: + +.. code-block:: js + +.. code-block:: diff + + Encore + // ... + + .splitEntryChunks() + + .configureSplitChunks(function(splitChunks) { + + // change the configuration + + splitChunks.minSize = 0; + + } + +.. _`SplitChunksPlugin from Webpack`: https://webpack.js.org/plugins/split-chunks-plugin/ diff --git a/frontend/encore/typescript.rst b/frontend/encore/typescript.rst index 10d363897b5..03cf18eac8d 100644 --- a/frontend/encore/typescript.rst +++ b/frontend/encore/typescript.rst @@ -1,66 +1,37 @@ Enabling TypeScript (ts-loader) =============================== -Want to use `TypeScript`_? No problem! First, install the dependencies: +Want to use `TypeScript`_? No problem! First, enable it: -.. code-block:: terminal - - $ yarn add --dev typescript ts-loader@^3.0 - -Then, activate the ``ts-loader`` in ``webpack.config.js``: - -.. code-block:: javascript +.. code-block:: diff // webpack.config.js // ... Encore // ... - .addEntry('main', './assets/main.ts') - - .enableTypeScriptLoader() - ; - -That's it! Any ``.ts`` files that you require will be processed correctly. You can -also configure the `ts-loader options`_ via a callback: - -.. code-block:: javascript - - .enableTypeScriptLoader(function (typeScriptConfigOptions) { - typeScriptConfigOptions.transpileOnly = true; - typeScriptConfigOptions.configFile = '/path/to/tsconfig.json'; - }); - -If React assets are enabled (``.enableReactPreset()``), any ``.tsx`` file will be -processed as well by ``ts-loader``. - -More information about the ``ts-loader`` can be found in its `README`_. + + .addEntry('main', './assets/main.ts') -Faster Builds with fork-ts-checker-webpack-plugin -------------------------------------------------- + + .enableTypeScriptLoader() -By using `fork-ts-checker-webpack-plugin`_, you can run type checking in a separate -process, which can speedup compile time. To enable it, install the plugin: - -.. code-block:: terminal - - $ yarn add --dev fork-ts-checker-webpack-plugin - -Then enable it by calling: + // optionally enable forked type script for faster builds + // https://www.npmjs.com/package/fork-ts-checker-webpack-plugin + // requires that you have a tsconfig.json file that is setup correctly. + + //.enableForkedTypeScriptTypesChecking() + ; -.. code-block:: javascript +Then restart Encore. When you do, it will give you a command you can run to +install any missing dependencies. After running that command and restarting +Encore, you're done! - // webpack.config.js - - Encore - // ... - .enableForkedTypeScriptTypesChecking() - ; +Any ``.ts`` files that you require will be processed correctly. You can +also configure the `ts-loader options`_ via the ``enableTypeScriptLoader()`` +method. See the `Encore's index.js file`_ for detailed documentation. -This plugin requires that you have a `tsconfig.json`_ file that is setup correctly. +If React is enabled (``.enableReactPreset()``), any ``.tsx`` file will also be +processed by ``ts-loader``. .. _`TypeScript`: https://www.typescriptlang.org/ .. _`ts-loader options`: https://github.com/TypeStrong/ts-loader#options -.. _`README`: https://github.com/TypeStrong/ts-loader#typescript-loader-for-webpack .. _`fork-ts-checker-webpack-plugin`: https://www.npmjs.com/package/fork-ts-checker-webpack-plugin -.. _`tsconfig.json`: https://www.npmjs.com/package/fork-ts-checker-webpack-plugin#modules-resolution +.. _`Encore's index.js file`: https://github.com/symfony/webpack-encore/blob/master/index.js diff --git a/frontend/encore/versioning.rst b/frontend/encore/versioning.rst index d2eb033c2cb..a5ec30256fd 100644 --- a/frontend/encore/versioning.rst +++ b/frontend/encore/versioning.rst @@ -20,26 +20,37 @@ ignoring any existing cache: // ... + .enableVersioning() -To link to these assets, Encore creates a ``manifest.json`` file with a map to -the new filenames. +To link to these assets, Encore creates two files ``entrypoints.json`` and +``manifest.json``. .. _load-manifest-files: -Loading Assets from the manifest.json File ------------------------------------------- +Loading Assets from entrypoints.json & manifest.json +---------------------------------------------------- -Whenever you run Encore, a ``manifest.json`` file is automatically -created in your ``outputPath`` directory: +Whenever you run Encore, two configuration files are generated: ``entrypoints.json`` +and ``manifest.json``. Each file is similar, and contains a map to the final, versioned +filename. + +The first file - ``entrypoints.json`` - is used by the ``encore_entry_script_tags()`` +and ``encore_entry_link_tags()`` Twig helpers. If you're using these, then your +CSS and JavaScript files will render with the new, versioned filename. If you're +not using Symfony, your app will need to read this file in a similar way. + +The ``manifest.json`` file is only needed to get the versioned filename of *other* +files, like font files or image files (though it also contains information about +the CSS and JavaScript files): .. code-block:: json { "build/app.js": "/build/app.123abc.js", - "build/dashboard.css": "/build/dashboard.a4bf2d.css" + "build/dashboard.css": "/build/dashboard.a4bf2d.css", + "build/images/logo.png": "/build/images/logo.3eed42.png" } -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 +In your app, you need to read this file if you want to be able to link (e.g. via +an ``img`` tag) to certain assets. If you're using Symfony, just activate the ``json_manifest_file`` versioning strategy in ``config.yml``: .. code-block:: yaml @@ -56,9 +67,7 @@ like normal: .. code-block:: twig - - - + Learn more ---------- diff --git a/frontend/encore/vuejs.rst b/frontend/encore/vuejs.rst index e153316c148..a79755b2ff7 100644 --- a/frontend/encore/vuejs.rst +++ b/frontend/encore/vuejs.rst @@ -1,13 +1,7 @@ Enabling Vue.js (vue-loader) ============================ -Want to use `Vue.js`_? No problem! First, install Vue and some dependencies: - -.. code-block:: terminal - - $ yarn add --dev vue vue-loader@^14 vue-template-compiler - -Then, activate the ``vue-loader`` in ``webpack.config.js``: +Want to use `Vue.js`_? No problem! First enable it in ``webpack.config.js``: .. code-block:: diff @@ -21,18 +15,13 @@ Then, activate the ``vue-loader`` in ``webpack.config.js``: + .enableVueLoader() ; -That's it! Any ``.vue`` files that you require will be processed correctly. You can -also configure the `vue-loader options`_ via a callback: - -.. code-block:: javascript - - .enableVueLoader(function(options) { - // https://vue-loader.vuejs.org/options.html +Then restart Encore. When you do, it will give you a command you can run to +install any missing dependencies. After running that command and restarting +Encore, you're done! - options.preLoaders = { - js: '/path/to/custom/loader' - }; - }); +Any ``.vue`` files that you require will be processed correctly. You can also +configure the `vue-loader options`_ by passing an options callback to +``enableVueLoader()``. See the `Encore's index.js file`_ for detailed documentation. Hot Module Replacement (HMR) ---------------------------- @@ -43,7 +32,7 @@ your Vue.js app update *without* a browser refresh! To activate it, just use the .. code-block:: terminal - $ ./node_modules/.bin/encore dev-server --hot + $ yarn encore dev-server --hot That's it! Change one of your ``.vue`` files and watch your browser update. But note: this does *not* currently work for *style* changes in a ``.vue`` file. Seeing @@ -54,3 +43,4 @@ See :doc:`/frontend/encore/dev-server` for more details. .. _`babel-preset-react`: https://babeljs.io/docs/plugins/preset-react/ .. _`Vue.js`: https://vuejs.org/ .. _`vue-loader options`: https://vue-loader.vuejs.org/options.html +.. _`Encore's index.js file`: https://github.com/symfony/webpack-encore/blob/master/index.js