diff --git a/app/.gitignore b/app/.gitignore index a67f91e..7fdcc07 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -8,3 +8,10 @@ /var/ /vendor/ ###< symfony/framework-bundle ### + +###> symfony/webpack-encore-bundle ### +/node_modules/ +/public/build/ +npm-debug.log +yarn-error.log +###< symfony/webpack-encore-bundle ### diff --git a/app/assets/app.js b/app/assets/app.js new file mode 100644 index 0000000..bb0a6aa --- /dev/null +++ b/app/assets/app.js @@ -0,0 +1,12 @@ +/* + * Welcome to your app's main JavaScript file! + * + * We recommend including the built version of this JavaScript file + * (and its CSS file) in your base layout (base.html.twig). + */ + +// any CSS you import will output into a single css file (app.css in this case) +import './styles/app.css'; + +// start the Stimulus application +import './bootstrap'; diff --git a/app/assets/bootstrap.js b/app/assets/bootstrap.js new file mode 100644 index 0000000..58308a6 --- /dev/null +++ b/app/assets/bootstrap.js @@ -0,0 +1,11 @@ +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); diff --git a/app/assets/controllers.json b/app/assets/controllers.json new file mode 100644 index 0000000..a1c6e90 --- /dev/null +++ b/app/assets/controllers.json @@ -0,0 +1,4 @@ +{ + "controllers": [], + "entrypoints": [] +} diff --git a/app/assets/controllers/hello_controller.js b/app/assets/controllers/hello_controller.js new file mode 100644 index 0000000..8c79f65 --- /dev/null +++ b/app/assets/controllers/hello_controller.js @@ -0,0 +1,16 @@ +import { Controller } from 'stimulus'; + +/* + * This is an example Stimulus controller! + * + * Any element with a data-controller="hello" attribute will cause + * this controller to be executed. The name "hello" comes from the filename: + * hello_controller.js -> "hello" + * + * Delete this file or adapt it for your use! + */ +export default class extends Controller { + connect() { + this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js'; + } +} diff --git a/app/assets/styles/app.css b/app/assets/styles/app.css new file mode 100644 index 0000000..cb33b13 --- /dev/null +++ b/app/assets/styles/app.css @@ -0,0 +1,3 @@ +body { + background-color: lightgray; +} diff --git a/app/composer.json b/app/composer.json index 2824f03..26b484e 100644 --- a/app/composer.json +++ b/app/composer.json @@ -22,6 +22,7 @@ "symfony/security-csrf": "5.2.*", "symfony/twig-bundle": "5.2.*", "symfony/validator": "5.2.*", + "symfony/webpack-encore-bundle": "^1.11", "symfony/yaml": "5.2.*", "twig/extra-bundle": "^2.12|^3.0", "twig/twig": "^2.12|^3.0" diff --git a/app/composer.lock b/app/composer.lock index 116d595..15de535 100644 --- a/app/composer.lock +++ b/app/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6ffdfc77c62b6c1629f78d627f78e302", + "content-hash": "f25be7488ec574d0180bd5b54fd2544d", "packages": [ { "name": "composer/package-versions-deprecated", @@ -2034,6 +2034,75 @@ }, "time": "2021-04-09T16:14:11+00:00" }, + { + "name": "symfony/asset", + "version": "v5.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/asset.git", + "reference": "54a42aa50f9359d1184bf7e954521b45ca3d5828" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/asset/zipball/54a42aa50f9359d1184bf7e954521b45ca3d5828", + "reference": "54a42aa50f9359d1184bf7e954521b45ca3d5828", + "shasum": "" + }, + "require": { + "php": ">=7.2.5" + }, + "require-dev": { + "symfony/http-client": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/http-kernel": "^4.4|^5.0" + }, + "suggest": { + "symfony/http-foundation": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Asset\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/asset/tree/v5.2.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-27T10:01:46+00:00" + }, { "name": "symfony/cache", "version": "v5.2.6", @@ -5667,6 +5736,77 @@ ], "time": "2021-01-27T10:01:46+00:00" }, + { + "name": "symfony/webpack-encore-bundle", + "version": "v1.11.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/webpack-encore-bundle.git", + "reference": "395b60a549ded8e7f77f0d551815d7555e2d9eb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/webpack-encore-bundle/zipball/395b60a549ded8e7f77f0d551815d7555e2d9eb0", + "reference": "395b60a549ded8e7f77f0d551815d7555e2d9eb0", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "symfony/asset": "^4.4 || ^5.0", + "symfony/config": "^4.4 || ^5.0", + "symfony/dependency-injection": "^4.4 || ^5.0", + "symfony/http-kernel": "^4.4 || ^5.0", + "symfony/service-contracts": "^1.0 || ^2.0" + }, + "require-dev": { + "symfony/framework-bundle": "^4.4 || ^5.0", + "symfony/phpunit-bridge": "^4.4 || ^5.0", + "symfony/twig-bundle": "^4.4 || ^5.0", + "symfony/web-link": "^4.4 || ^5.0" + }, + "type": "symfony-bundle", + "extra": { + "thanks": { + "name": "symfony/webpack-encore", + "url": "https://github.com/symfony/webpack-encore" + } + }, + "autoload": { + "psr-4": { + "Symfony\\WebpackEncoreBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Integration with your Symfony app & Webpack Encore!", + "support": { + "issues": "https://github.com/symfony/webpack-encore-bundle/issues", + "source": "https://github.com/symfony/webpack-encore-bundle/tree/v1.11.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-02-17T13:45:51+00:00" + }, { "name": "symfony/yaml", "version": "v5.2.5", diff --git a/app/config/bundles.php b/app/config/bundles.php index 403d093..57064b1 100644 --- a/app/config/bundles.php +++ b/app/config/bundles.php @@ -9,4 +9,5 @@ return [ Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], + Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true], ]; diff --git a/app/config/packages/assets.yaml b/app/config/packages/assets.yaml new file mode 100644 index 0000000..051d36d --- /dev/null +++ b/app/config/packages/assets.yaml @@ -0,0 +1,3 @@ +framework: + assets: + json_manifest_path: '%kernel.project_dir%/public/build/manifest.json' diff --git a/app/config/packages/prod/webpack_encore.yaml b/app/config/packages/prod/webpack_encore.yaml new file mode 100644 index 0000000..d0b3ba8 --- /dev/null +++ b/app/config/packages/prod/webpack_encore.yaml @@ -0,0 +1,4 @@ +#webpack_encore: + # Cache the entrypoints.json (rebuild Symfony's cache when entrypoints.json changes) + # Available in version 1.2 + #cache: true diff --git a/app/config/packages/test/webpack_encore.yaml b/app/config/packages/test/webpack_encore.yaml new file mode 100644 index 0000000..02a7651 --- /dev/null +++ b/app/config/packages/test/webpack_encore.yaml @@ -0,0 +1,2 @@ +#webpack_encore: +# strict_mode: false diff --git a/app/config/packages/webpack_encore.yaml b/app/config/packages/webpack_encore.yaml new file mode 100644 index 0000000..90f1a1d --- /dev/null +++ b/app/config/packages/webpack_encore.yaml @@ -0,0 +1,30 @@ +webpack_encore: + # The path where Encore is building the assets - i.e. Encore.setOutputPath() + output_path: '%kernel.project_dir%/public/build' + # If multiple builds are defined (as shown below), you can disable the default build: + # output_path: false + + # Set attributes that will be rendered on all script and link tags + script_attributes: + defer: true + # link_attributes: + + # If using Encore.enableIntegrityHashes() and need the crossorigin attribute (default: false, or use 'anonymous' or 'use-credentials') + # crossorigin: 'anonymous' + + # Preload all rendered script and link tags automatically via the HTTP/2 Link header + # preload: true + + # Throw an exception if the entrypoints.json file is missing or an entry is missing from the data + # strict_mode: false + + # If you have multiple builds: + # builds: + # pass "frontend" as the 3rg arg to the Twig functions + # {{ encore_entry_script_tags('entry1', null, 'frontend') }} + + # frontend: '%kernel.project_dir%/public/frontend/build' + + # Cache the entrypoints.json (rebuild Symfony's cache when entrypoints.json changes) + # Put in config/packages/prod/webpack_encore.yaml + # cache: true diff --git a/app/package.json b/app/package.json new file mode 100644 index 0000000..ba0e4f4 --- /dev/null +++ b/app/package.json @@ -0,0 +1,18 @@ +{ + "devDependencies": { + "@symfony/stimulus-bridge": "^2.0.0", + "@symfony/webpack-encore": "^1.0.0", + "core-js": "^3.0.0", + "regenerator-runtime": "^0.13.2", + "stimulus": "^2.0.0", + "webpack-notifier": "^1.6.0" + }, + "license": "UNLICENSED", + "private": true, + "scripts": { + "dev-server": "encore dev-server", + "dev": "encore dev", + "watch": "encore dev --watch", + "build": "encore production --progress" + } +} diff --git a/app/symfony.lock b/app/symfony.lock index 9983ad4..94d246d 100644 --- a/app/symfony.lock +++ b/app/symfony.lock @@ -121,6 +121,9 @@ "config/packages/sensio_framework_extra.yaml" ] }, + "symfony/asset": { + "version": "v5.2.4" + }, "symfony/cache": { "version": "v5.2.6" }, @@ -346,6 +349,28 @@ "config/routes/dev/web_profiler.yaml" ] }, + "symfony/webpack-encore-bundle": { + "version": "1.9", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "1.9", + "ref": "9399a0bfc6ee7a0c019f952bca46d6a6045dd451" + }, + "files": [ + "assets/app.js", + "assets/bootstrap.js", + "assets/controllers.json", + "assets/controllers/hello_controller.js", + "assets/styles/app.css", + "config/packages/assets.yaml", + "config/packages/prod/webpack_encore.yaml", + "config/packages/test/webpack_encore.yaml", + "config/packages/webpack_encore.yaml", + "package.json", + "webpack.config.js" + ] + }, "symfony/yaml": { "version": "v5.2.5" }, diff --git a/app/webpack.config.js b/app/webpack.config.js new file mode 100644 index 0000000..056b04a --- /dev/null +++ b/app/webpack.config.js @@ -0,0 +1,75 @@ +const Encore = require('@symfony/webpack-encore'); + +// Manually configure the runtime environment if not already configured yet by the "encore" command. +// It's useful when you use tools that rely on webpack.config.js file. +if (!Encore.isRuntimeEnvironmentConfigured()) { + Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev'); +} + +Encore + // directory where compiled assets will be stored + .setOutputPath('public/build/') + // public path used by the web server to access the output path + .setPublicPath('/build') + // only needed for CDN's or sub-directory deploy + //.setManifestKeyPrefix('build/') + + /* + * ENTRY CONFIG + * + * 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') + + // 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() + + // will require an extra script tag for runtime.js + // but, you probably want this, unless you're building a single-page app + .enableSingleRuntimeChunk() + + /* + * FEATURE CONFIG + * + * Enable & configure other features below. For a full + * list of features, see: + * https://symfony.com/doc/current/frontend.html#adding-more-features + */ + .cleanupOutputBeforeBuild() + .enableBuildNotifications() + .enableSourceMaps(!Encore.isProduction()) + // 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'; + config.corejs = 3; + }) + + // enables Sass/SCSS support + //.enableSassLoader() + + // 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() +; + +module.exports = Encore.getWebpackConfig();