diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6c10a4eaf9b..6750bd8eb20 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -118,7 +118,7 @@ jobs: - name: Install dependencies if: ${{ steps.find-files.outputs.files }} - run: composer create-project symfony-tools/code-block-checker _checker + run: composer create-project symfony-tools/code-block-checker:@dev _checker - name: Install test application if: ${{ steps.find-files.outputs.files }} diff --git a/_build/redirection_map b/_build/redirection_map index 1acae2a1667..e7146d2fc2d 100644 --- a/_build/redirection_map +++ b/_build/redirection_map @@ -513,6 +513,7 @@ /components/stopwatch https://github.com/symfony/stopwatch /service_container/3.3-di-changes https://symfony.com/doc/3.4/service_container/3.3-di-changes.html /frontend/encore/shared-entry /frontend/encore/split-chunks +/frontend/encore/page-specific-assets /frontend/encore/simple-example#page-specific-javascript-or-css /testing/functional_tests_assertions /testing#testing-application-assertions /components https://symfony.com/components /components/index https://symfony.com/components diff --git a/frontend.rst b/frontend.rst index 30202523b41..4272cb8338d 100644 --- a/frontend.rst +++ b/frontend.rst @@ -40,7 +40,7 @@ Getting Started ............... * :doc:`Installation ` -* :doc:`First Example ` +* :doc:`Using Webpack Encore ` Adding more Features .................... @@ -67,7 +67,6 @@ 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) ` diff --git a/frontend/encore/installation.rst b/frontend/encore/installation.rst index c53dddd5d3f..eb4b82e8b45 100644 --- a/frontend/encore/installation.rst +++ b/frontend/encore/installation.rst @@ -82,15 +82,13 @@ is the main config file for both Webpack and Webpack Encore: /* * ENTRY CONFIG * - * Add 1 entry for each "page" of your app - * (including one that's included on every page - e.g. "app") - * * Each entry will result in one JavaScript file (e.g. app.js) * and one CSS file (e.g. app.css) if your JavaScript imports CSS. */ .addEntry('app', './assets/app.js') - //.addEntry('page1', './assets/page1.js') - //.addEntry('page2', './assets/page2.js') + + // enables the Symfony UX Stimulus bridge (used in assets/bootstrap.js) + .enableStimulusBridge('./assets/controllers.json') // When enabled, Webpack "splits" your files into smaller pieces for greater optimization. .splitEntryChunks() @@ -112,6 +110,10 @@ is the main config file for both Webpack and Webpack Encore: // enables hashed filenames (e.g. app.abc123.css) .enableVersioning(Encore.isProduction()) + .configureBabel((config) => { + config.plugins.push('@babel/plugin-proposal-class-properties'); + }) + // enables @babel/preset-env polyfills .configureBabelPresetEnv((config) => { config.useBuiltIns = 'usage'; @@ -124,16 +126,15 @@ is the main config file for both Webpack and Webpack Encore: // uncomment if you use TypeScript //.enableTypeScriptLoader() + // uncomment if you use React + //.enableReactPreset() + // uncomment to get integrity="..." attributes on your script & link tags // requires WebpackEncoreBundle 1.4 or higher //.enableIntegrityHashes(Encore.isProduction()) // uncomment if you're having problems with a jQuery plugin //.autoProvidejQuery() - - // uncomment if you use API Platform Admin (composer require api-admin) - //.enableReactPreset() - //.addEntry('admin', './assets/admin.js') ; module.exports = Encore.getWebpackConfig(); @@ -154,10 +155,8 @@ Next, open the new ``assets/app.js`` file which contains some JavaScript code // any CSS you import will output into a single css file (app.css in this case) import './styles/app.css'; - // Need jQuery? Install it with "yarn add jquery"(or "npm install jquery"), then uncomment to import it. - // import $ from 'jquery'; - - console.log('Hello Webpack Encore! Edit me in assets/app.js'); + // start the Stimulus application + import './bootstrap'; And the new ``assets/styles/app.css`` file: @@ -168,7 +167,37 @@ And the new ``assets/styles/app.css`` file: background-color: lightgray; } +You should also add an ``assets/bootstrap.js`` file, which initializes Stimulus: +a system that you'll learn about soon: + +.. code-block:: javascript + + // assets/bootstrap.js + import { startStimulusApp } from '@symfony/stimulus-bridge'; + + // Registers Stimulus controllers from controllers.json and in the controllers/ directory + export const app = startStimulusApp(require.context( + '@symfony/stimulus-bridge/lazy-controller-loader!./controllers', + true, + /\.(j|t)sx?$/ + )); + + // register any custom, 3rd party controllers here + // app.register('some_controller_name', SomeImportedController); + +And finally, create an ``assets/controllers.json`` file, which also fits into +the Stimulus system: + +```json +{ + "controllers": [], + "entrypoints": [] +} +``` + You'll customize and learn more about these files in :doc:`/frontend/encore/simple-example`. +When you execute Encore, it will ask you to install a few more dependencies based +on which features of Encore you have enabled. .. caution:: diff --git a/frontend/encore/page-specific-assets.rst b/frontend/encore/page-specific-assets.rst deleted file mode 100644 index 8f03bfb5877..00000000000 --- a/frontend/encore/page-specific-assets.rst +++ /dev/null @@ -1,27 +0,0 @@ -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. - -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. Think of the -checkout page as its own "app", where ``checkout.js`` includes all the functionality -you need. - -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 use :doc:`split chunks ` - to avoid duplicate and shared code between your entry files. diff --git a/frontend/encore/simple-example.rst b/frontend/encore/simple-example.rst index 8fa55913d69..64115878107 100644 --- a/frontend/encore/simple-example.rst +++ b/frontend/encore/simple-example.rst @@ -1,11 +1,14 @@ Encore: Setting up your Project =============================== -After :doc:`installing Encore `, your app already has one -CSS and one JS file, organized into an ``assets/`` directory: +After :doc:`installing Encore `, your app already +has a few files, organized into an ``assets/`` directory: * ``assets/app.js`` +* ``assets/bootstrap.js`` +* ``assets/controllers.json`` * ``assets/styles/app.css`` +* ``assets/controllers/hello_controller.js`` 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), @@ -19,11 +22,14 @@ application: it will *require* all of the dependencies it needs (e.g. jQuery or import './styles/app.css'; -Encore's job (via Webpack) is simple: to read and follow *all* of the ``require()`` +Encore's job (via Webpack) is simple: to read and follow *all* of the ``import`` statements and create one final ``app.js`` (and ``app.css``) that contains *everything* your app needs. Encore can do a lot more: minify files, pre-process Sass/LESS, support React, Vue.js, etc. +The other files - ``bootstrap.js``, ``controllers.json`` and ``hello_controller.js`` +relate to a topic you'll learn about soon: `Stimulus & Symfony UX`_. + Configuring Encore/Webpack -------------------------- @@ -59,27 +65,24 @@ To build the assets, run the following if you use the Yarn package manager: .. code-block:: terminal - # compile assets once - $ yarn encore dev - - # or, recompile assets automatically when files change - $ yarn encore dev --watch + # compile assets and automatically re-compile when files change + $ yarn watch - # on deploy, create a production build - $ yarn encore production + # if using npm, use "npm run" and then any of these commands + $ npm run watch -If you use the npm package manager, run the following commands instead: - -.. code-block:: terminal + # or, run a dev-server that can sometimes update your code without refreshing the page + $ yarn dev-server # compile assets once - $ npm run dev - - # or, recompile assets automatically when files change - $ npm run watch + $ yarn dev # on deploy, create a production build - $ npm run build + $ yarn build + +All of these commands - e.g. ``dev`` or ``watch`` - are shortcuts that are defined +in your ``package.json`` file. If you use the npm package manager, replace ``yarn`` +with ``npm run``. .. note:: @@ -91,8 +94,15 @@ Congrats! You now have three new files: * ``public/build/app.css`` (holds all the CSS for your "app" entry) * ``public/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: +.. note:: + + In reality, you probably have a few *more* files in ``public/build``. Some of + these are due to :doc:`code splitting `, an optimization + that helps performance, but doesn't affect how things work. Others help Encore + do its work. + +Next, to include these in your base layout, you can leverage two Twig helpers from +WebpackEncoreBundle: .. code-block:: html+twig @@ -130,7 +140,7 @@ That's it! When you refresh your page, all of the JavaScript from 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 +read from a ``public/build/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 @@ -155,7 +165,7 @@ Requiring JavaScript Modules ---------------------------- Webpack is a module bundler, which means that you can ``import`` other JavaScript -files. First, create a file that exports a function: +files. First, create a file that exports a function, class or any other value: .. code-block:: javascript @@ -196,14 +206,121 @@ 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! +Stimulus & Symfony UX +--------------------- + +As simple as the above example is, instead of building your application inside of +``app.js``, we recommend `Stimulus`_: a small JavaScript framework that makes it +easy to attach behavior to HTML. It's powerful, and you will love it! Symfony +even provides packages to add more features to Stimulus. These are called the +`Symfony UX Packages`_. + +If you followed the setup instructions, you should already have Stimulus installed +and ready to go! In fact, that's the purpose of the ``assets/bootstrap.js`` file: +to initialize Stimulus and automatically load any "controllers" from the +``assets/controllers/`` directory. + +Let's look at a simple Stimulus example. In a Twig template, suppose you have: + +.. code-block:: twig + +