symfony / webpack-encore-bundle Goto Github PK
View Code? Open in Web Editor NEWSymfony integration with Webpack Encore!
Home Page: https://symfony.com/webpack-encore
License: MIT License
Symfony integration with Webpack Encore!
Home Page: https://symfony.com/webpack-encore
License: MIT License
Hello,
Twig functions encore_entry_link_tags / encore_entry_script_tags throw an exception if assets are not compiled:
An exception has been thrown during the rendering of a template ("Could not find the entrypoints file from Webpack: the file "/var/www/app/public/build/entrypoints.json" does not exist.")
This behavior is annoying when it comes to functional testing. Because building assets for symfony crawler tests is a waste of time.
Currently, I'm using this workaround
<head>
{% if app.environment != 'test' %}{{ encore_entry_link_tags('app') }}{% endif %}
</head>
<body>
{% if app.environment != 'test' %}{{ encore_entry_script_tags('app') }}{% endif %}
</body>
It would be nice to have an option not to throw exceptions for the test environment.
Hi,
I'd like to display script tags only if the entry exists using a Twig function like encore_entry_script_tags_if_exists
.
As I know, there is actually no public method to check if an entry is defined for a given entry point.
Do you think this is possible to add such a behavior?
Thanks
Prior to v1.1.0 it was possible to fetch webpack_encore.entrypoint_lookup
from the container to interact with the EntrypointLookup
class. Now when fetching webpack_encore.entrypoint_lookup
from the container we get the following exception:
FatalExceptionError
Type error: Argument 1 passed to Symfony\WebpackEncoreBundle\Asset\EntrypointLookup::__construct() must be of the type string, object given, called in /vagrant/var/cache/prod/Container3svdnsj/getWebpackEncore_EntrypointLookupService.php on line 8
Looking at WebpackEncoreExtension
the following line appears to be the culprit:
$container->getDefinition('webpack_encore.entrypoint_lookup')
->replaceArgument(0, $factories['_default']);
Not being very familiar with the container and the way it works I can only speculate that it's not being resolved from the container correctly and passing the object itself rather than the output path.
Calling webpack_encore.entrypoint_lookup[_default]
works fine as a temporary workaround but it's not an ideal solution.
PHP: 7.1.8
symfony/symfony
: 3.4.20
symfony/webpack-encore-bundle
: v1.1.0
Using this bundle (v1.6.0) with Symfony 4.3 will have Composer generate a couple of "Warning: Ambiguous class resolution" when trying to generate an optimized autoloader.
$ composer dump-autoload --optimize
Generating optimized autoload files
Warning: Ambiguous class resolution, "Symfony\Contracts\Cache\CallbackInterface" was found in both "/var/www/vendor/symfony/cache-contracts/CallbackInterface.php" and "/var/www/vendor/symfony/contracts/Cache/CallbackInterface.php", the first will be used.
Warning: Ambiguous class resolution, "Symfony\Contracts\Cache\ItemInterface" was found in both "/var/www/vendor/symfony/cache-contracts/ItemInterface.php" and "/var/www/vendor/symfony/contracts/Cache/ItemInterface.php", the first will be used.
Warning: Ambiguous class resolution, "Symfony\Contracts\Cache\CacheInterface" was found in both "/var/www/vendor/symfony/cache-contracts/CacheInterface.php" and "/var/www/vendor/symfony/contracts/Cache/CacheInterface.php", the first will be used.
(snip)
The framework will load some traits and interfaces from /symfony/service-contracts/ while /webpack-encore-bundle/ will try to load the same from /symfony/contracts/
$ composer why symfony/contracts
symfony/webpack-encore-bundle v1.6.0 requires symfony/contracts (^1.0)
$ composer why symfony/service-contracts
symfony/cache v4.3.0 requires symfony/service-contracts (^1.1)
symfony/console v4.3.0 requires symfony/service-contracts (^1.1)
symfony/dependency-injection v4.3.0 requires symfony/service-contracts (^1.1.2)
symfony/doctrine-bridge v4.3.0 requires symfony/service-contracts (^1.1)
symfony/expression-language v4.3.0 requires symfony/service-contracts (^1.1)
symfony/monolog-bridge v4.3.0 requires symfony/service-contracts (^1.1)
symfony/security-core v4.3.0 requires symfony/service-contracts (^1.1)
symfony/stopwatch v4.3.0 requires symfony/service-contracts (^1.0)
Could this bundle bump it's requirement to symfony/service-contracts too?
In Encore, the css
key for an asset may be missing entirely. Let's make sure the EntrypointLookup can handle a missing css
key (just return no assets).
Basically the title explains it all. When running
yarn encore production
webpack still produces the build for dev, not production. According to the source code of node_modules/.bin/encore, webpack/bin/webpack is being used for non dev environment. However, webpack/bin/webpack doesn't seem to execute in the production mode.
When using encore_entry_script_tags
to load a script, if this script make an early async request, it may occur before the loading of the Symfony web debug toolbar. In this case, this request is not detected and doesn't appear in the "AJAX requests" panel of the debug bar.
In dev mode, maybe can we hack something to make sure that the debug bar is loaded before Encore loads the external scripts?
We currently work on a pull request for heimrichhannot/contao-encore-bundle#8 to integrate Encore in the Contao CMS. We need the names of all available entries from the entrypoints.json for the backend. Sadly we can't use the EntrypointLookup since it doesn't have a method for this.
If we could add a getAllEntries to the EntrypointLookupInterface, we wouldn't have to duplicate code and could parse the entrypoints.json only at one single location.
I can try to make a fitting pull request.
Related #87
When you encore_entry_link_tags()
or encore_entry_script_tags()
tags, the bundle "remembers" which CSS and JS files have been rendered and avoids rendering them again. This is by design: it allows you to render multiple "entries" on the same page and avoid link/script tags for the same CSS & JS files (due to code splitting).
But, this has some nasty side effects. One practical one is sending emails and using these functions to import your CSS. If you have Messenger installed, each Email is technically rendered twice - and the second (real) email will contain no CSS link tags. The problem is probably worse when sending emails through the queue - as I think once a worker has sent one email, the rest won't contain CSS link tags.
The best solution would be to reset "automatically" the cache after a "main" Twig rendering (e.g. a call to$twig->render()
) but no such concept currently exists in Twig.
A more immediate solution may be to allow users to "opt out" of the cache via some argument to encore_entry_link_tags()
.
The build name in the example below will change from some-name
to some_name
due to array key normalization of the configuration component.
webpack_encore:
output_path: '%kernel.project_dir%/public/static/'
builds:
some-name: '%kernel.project_dir%/public/static/some-name'
Resulting in an UndefinedBuildException:
An exception has been thrown during the rendering of a template ("Given entry point "some-name" is not configured").
When I call
{{ encore_entry_link_tags('frontend', null, 'some-name' }}
It does work when I use the following line:
{{ encore_entry_link_tags('frontend', null, 'some_name' }}
I don't see any reason to normalize the keys of the builds config. I should be free to choose whatever name I want for my build, right?
Hello,
I think it would be interesting if I could pass to encore_entry_link_tags and encore_entry_script_tags functions that I want to generate tags with absolute url. Now, if I want to get absolute url, I can't use encore_entry_link_tags and encore_entry_script_tags.
The latest version 1.4.0 with the Encore. enableIntegrityHashes() function from @symfony/webpack-encore version 0.26.0
Generates code like:
<link rel="stylesheet" href="https://cdn.example.com/webpack/css_main_header.03d68e17.css?v=1554057765" integrity="sha384-2ZeLK3oSpOQmeB6N947S85lqfOVaKdknVpsVOJ0u+F6sohBFltWQ/bLpwAcjayoi">
<script src="https://cdn.example.com/webpack/runtime.6601bbb6.js?v=1554057765" integrity="sha384-cEq/N+NkEWk8qaypIggtQLcs8ib4ZmONrlkGkwJadcQ3+oXVSXHLh49cUXCOGjje"></script>
which when deployed will result in a broken site and red in the console log of chrome with message like
...has an integrity attribute, but the resource requires the request to be CORS enabled to check the integrity, and it is not. The resource has been blocked because the integrity cannot be enforced.
This is because the tags are missing the attribute
crossorigin="anonymous"
(View the source of this github page to see how github do this)
This makes enableIntegrityHashes() currently useless in Symfony 4.
Hello,
I have multiple concerns reguarding the preload
feature that has been introduced in a recent PR
This option adds all the resources included with the {{ encore_* }}
tag in the response link
header in order to preload the resources.
One thing that bugs me is that it's very aggressive approach to tell the application: "Ok let's push ALL the resources from the application"
1/ Because it can hurt web performance to push large assets using the link header.
Preloading everything won’t magically speed up the site – instead, it will likely prevent the browser from scheduling everything smartly. - Source
There are certain situations where Preload works better than Push and vice-versa. Neither preload or push should be used as a way to speed up the delivery of all your assets at once. Instead you should determine what your high-priority resources are and go from there. - Source
2/ Because it's not flexible enough, sometimes you just want to preload the resource and not push it (which require http2) with the nopush
attribute.
3/ The key is confusing, preload
is not true when you have HTTP2 protocol. It will push the asset to the client and not preload it. Only if you're stuck in HTTP1.1 protocol, it will "only" preload it.
4/ The prefetch
strategy is missing and can't be handled globally or per entries. It should be used per "usage" or per "call" if you prefer.
1/ 👎 Tweak the global configuration preload: true
to add a way to not push it.
preload:
enabled: true
push: false
Will translate to:
</build/runtime.fa8f03f5.js>; rel="preload"; as="script"; nopush
in the link
header
2/ 👍 I think a better approach would be defining a strategy by entries:
entry-A:
preload:
enabled: true
nopush: false
entry-B:
preload:
enabled: true
nopush: true
However this configuration would not solve point number 4/
For example, if you know that a visitor is likely to visit page B after visiting page A, it would be interesting to apply either the prefetch
strategy, (or the prerender
strategy but that's covered in the WebLink component).
On page A you would for example use
{{ encore_entry_script_tags('entry.a', { strategy: 'prefetch' }) }}
If those strategy is used, nothing will be outputted in the DOM. Instead, in the response header, you'll have under the key link
entry:
</build/0.c1867cb2.js>; rel="prefetch"; as="script",</build/0.c1867cb2.js>; rel="prefetch"; as="script"
--
I'll tag @weaverryan because I saw that you needed feedback on this subject (for example here: #14)
Thanks.
Hi,
I'm trying to make Webpack Encore's dev-server working with the new Twig CSS Inliner extension but I'm facing an issue.
I'm using Encore to build Foundation .css
files because we want to keep Foundation up-to-date by using npm or yarn, and so I can't directly import a .css
like described in the documentation.
This is a part of my webpack.config.js
:
Encore
.addEntry('email', './assets/email/foundation.scss')
.addEntry('email-responsive', './assets/email/foundation.responsive.css')
This is a part of my config/packages/twig.yaml
:
twig:
paths:
'%kernel.project_dir%/public/build': build # I can use `source('@build/...')`
And this is my base email template, which works when running encore dev
or encore production
:
{% set css_to_inline = encore_entry_css_files('email')
| map(stylesheet => stylesheet|replace({ '/build': '@build' }))
| map(stylesheet => source(stylesheet))
%}
{% set css_to_ship = encore_entry_css_files('email-responsive')
| map(stylesheet => stylesheet|replace({ '/build': '@build' }))
| map(stylesheet => source(stylesheet))
%}
{% apply inky|inline_css(css_to_inline|join('')) %}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style>
{{ css_to_ship|join('') }}
</style>
<table class="body" data-made-with-foundation>
<tr>
<td class="float-center" align="center" valign="middle">
<!-- .... -->
</td>
</tr>
</table>
{% endapply %}
But when running encore dev-server
, I have the following error when sending an email:
And this is normal because Twig can not load files from an URL.
A solution would be to introduce a new Twig method encore_is_dev_server()
which will returns true
or false
depending Encore environment. I think this method would read a (new) .json
file generated by Encore.
With this new method, I would be able to write something like this and have emails that support Encore dev/prod/dev-server environments:
{% if not encore_is_dev_server() %}
{% set css_to_inline = encore_entry_css_files('email')
| map(stylesheet => stylesheet|replace({ '/build': '@build' }))
| map(stylesheet => source(stylesheet))
%}
{% endif %}
{% apply inky|inline_css(css_to_inline|default([])|join('')) %}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
{% if encore_is_dev_server() %}
{{ encore_entry_link_tags('email') }}
{{ encore_entry_link_tags('email-responsive') }}
{% else %}
<style>
{{ encore_entry_css_files('email-responsive')
| map(stylesheet => stylesheet|replace({ '/build': '@build' }))
| map(stylesheet => source(stylesheet))
| join('') }}
</style>
{% endif %}
<table class="body" data-made-with-foundation>
<tr>
<td class="float-center" align="center" valign="middle">
<!-- ... -->
</td>
</tr>
</table>
{% endapply %}
What do you think?
Thanks!
We have a case where our css and js files are on a cdn and we have encore build all the files remotely on the cdn after we do a push. the entrypoints.json is therefore also remotely on the cdn server.
I can add this in the config:
webpack_encore:
output_path: "https://cdn.blabla.com/experimental"
But then the file_exists check in src/Asset/EntryPointLookup.php on line 120 halts the process.
Whereas the file_get_contents on line 127 would work perfectly well with the remote url.
So could there be a way to bypass the file_exists check if the output_path is a url? Or add a config option "remote" or something like that?
I have stuff like @import '../assets/scss/WebsiteBundle/font.scss';
in scss/WebsiteBundle/default.scss
, however, since Symfony 4.4 I get the following depracitation warning.
Loading the file "../assets/../_photo.scss" from the global resource directory ".../src" is deprecated since Symfony 4.4 and will be removed in 5.0.
After upgrading to 5.0 CSS is (as expected) broken.
I can't seem to find anything in the documentation about this. How should I proceed?
I’m not sure how to implement this or if the bundle even want to support it. But I would like some assets to be loaded asynchronously.
In the best of all worlds, I would like my base (header, sidebar) css to be loaded sync and the rest could be loaded async.
———
I’ve taken some inspiration from this YouTube video. https://youtu.be/d5_6yHixpsQ
I just added webpack-encore-bundle
to an existing Symfony 4 project using:
$ composer require symfony/webpack-encore-bundle
$ yarn install
The following files have been created alright:
However, to my surprise, the following files have not been updated:
.gitignore
does not contain the usual exclusions like node_modules, public/build, etc.config/bundles.php
does not contain the WebpackEncoreBundle
entryI did the same setup on another existing project a few weeks ago, and the files had been correctly updated.
For the webpack_encore.entrypoint_lookup_collection
service, we're currently NEVER passing the 2nd argument: $defaultBuildName
. In WebpackEncoreExtension
, we should set this argument to _default
inside this if statement:
I use a xampp server for developping the Symfony 4 app.
i use yarn encore dev --watch
the files are stored correctly, but the rendered links are wrong.
i use
{{ encore_entry_script_tags('app') }}
in the twig template
the rendered link is only: src="/build/app.js"
webpack.config,js
.setOutputPath('public/build/')
.setPublicPath('/build')
.setManifestKeyPrefix('build/')
.addEntry('app', './assets/js/app.js')
webpack_encore.yaml
output_path: '%kernel.project_dir%/public/build'
Hey!
I've tries to fix a few deprecations with MicroKernelTrait
in my code after updating to Symfony 5.1 and tried to see how this was fixed in custom bundles.
Look here:
webpack-encore-bundle/tests/IntegrationTest.php
Lines 267 to 281 in 5c0f659
configureRouting(RoutingConfigurator $routes)
will be implemented when configureRouting
will exist, or configureRoutes(RouteCollectionBuilder $routes)
when it does not exist.
Looks like this configureRouting
was implemented here (probably in some of 5.1-dev), but then it was reverted here (when Symfony 5.1 was released).
So, configureRouting
will never actually exist, and method configureRoutes(RouteCollectionBuilder $routes)
will always be implemented.
But RouteCollectionBuilder
was deprecated since 5.1 and we must use some sort of
if (^5.1) {
protected function configureRoutes(RoutingConfigurator $routes): void { ... }
} else {
protected function configureRoutes(RouteCollectionBuilder $routes) { ... }
}
We cannot simply omit the type declaration (protected function configureRoutes($routes)
), as it is checked by the BC layer:
https://github.com/symfony/symfony/blob/e5b5d9ea14ef8141c20b79bbeaae360f1afbdc55/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php#L168-L174
Do you have any ideas how to check this without using version comparison?
When calling encore_entry_link_tags()
in a Twig template, the underlying PHP code has some safe-guarding in place to ensure the same link tag isn't outputted twice:
webpack-encore-bundle/src/Asset/EntrypointLookup.php
Lines 84 to 89 in 5e1cab3
I'm not entirely sure of the rationale behind this, but it causes an issue when encore_entry_link_tags()
is called twice in the same request.
This issue came to light when investigating why an order confirmation page of a website wasn't outputting a stylesheet's link
tag. After some debugging I figured out it was because the controller for this page sends a confirmation email with an attached PDF which is rendered via HTML/Twig.
The Twig template for the PDF called encore_entry_link_tags()
, so when the confirmation page was loaded and encore_entry_link_tags()
was called a second time, nothing was returned.
I have worked around this by calling the reset()
method of the EntrypointLookup
object right after the confirmation email is sent but it feels like a bit of a hack.
Why does the "make sure to not return the same file multiple times" code need to be there? Can it be removed, or can the issue it solves be solved in a different way?
Relevant Slack discussion: https://symfony-devs.slack.com/archives/C5VHNHY11/p1562584991057800
I'm using this function to render PDF with inline CSS as it was suggested in #16 (comment):
<style>{{ asset_get_content(encore_entry_css_files('pdf')) }}</style>
But if I call the twig render
method multiple time (to render multiple PDFs on one command), only the first will get CSS.
For the other, the css file list is just empty.
So I tried this for test on my homepage:
{{ dump(encore_entry_css_files('pdf')) }}
{{ dump(encore_entry_css_files('pdf')) }}
{{ dump(encore_entry_css_files('pdf')) }}
And it confirms the issue:
To me, it's a bug. Why this function would not return the needed files if call multiple times?
Error: Encore.setOutputPath() cannot be called yet because the runtime environment doesn't appear to be configured. Make sure you're using the encore executable
or call Encore.configureRuntimeEnvironment() first if you're purposely not calling Encore directly.
at Object.get (D:\phpstudy\www\drupai\node_modules@symfony\webpack-encore\index.js:1219:23)
at Object. (D:\phpstudy\www\drupai\webpack.config.js:5:6)
at Module._compile (D:\phpStudy\WWW\drupai\node_modules\v8-compile-cache\v8-compile-cache.js:178:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
at Module.load (internal/modules/cjs/loader.js:599:32)
at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
at Function.Module._load (internal/modules/cjs/loader.js:530:3)
at Module.require (internal/modules/cjs/loader.js:637:17)
at require (D:\phpStudy\WWW\drupai\node_modules\v8-compile-cache\v8-compile-cache.js:159:20)
at WEBPACK_OPTIONS (D:\phpStudy\WWW\drupai\node_modules\webpack-cli\bin\convert-argv.js:115:13)
at requireConfig (D:\phpStudy\WWW\drupai\node_modules\webpack-cli\bin\convert-argv.js:117:6)
at D:\phpStudy\WWW\drupai\node_modules\webpack-cli\bin\convert-argv.js:124:17
at Array.forEach ()
at module.exports (D:\phpStudy\WWW\drupai\node_modules\webpack-cli\bin\convert-argv.js:122:15)
at yargs.parse (D:\phpStudy\WWW\drupai\node_modules\webpack-cli\bin\cli.js:232:39)
at Object.parse (D:\phpStudy\WWW\drupai\node_modules\webpack-cli\node_modules\yargs\yargs.js:567:18)
at D:\phpStudy\WWW\drupai\node_modules\webpack-cli\bin\cli.js:210:8
at Object. (D:\phpStudy\WWW\drupai\node_modules\webpack-cli\bin\cli.js:500:3)
at Module._compile (internal/modules/cjs/loader.js:689:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
at Module.load (internal/modules/cjs/loader.js:599:32)
at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
at Function.Module._load (internal/modules/cjs/loader.js:530:3)
at Module.require (internal/modules/cjs/loader.js:637:17)
at require (internal/modules/cjs/helpers.js:20:18)
at Object. (D:\phpStudy\WWW\drupai\node_modules\webpack\bin\webpack.js:155:2)
at Module._compile (internal/modules/cjs/loader.js:689:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
at Module.load (internal/modules/cjs/loader.js:599:32)
at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
at Function.Module._load (internal/modules/cjs/loader.js:530:3)
at Module.require (internal/modules/cjs/loader.js:637:17)
at require (internal/modules/cjs/helpers.js:20:18)
at Object. (D:\phpStudy\WWW\drupai\node_modules@symfony\webpack-encore\bin\encore.js:63:12)
at Module._compile (internal/modules/cjs/loader.js:689:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
why use this bundle in symfony4, this is a lot of problen?
Hello, I'm using this simple base.html.twig
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
{% block stylesheets %} {{ encore_entry_link_tags('app') }}
{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
{% block javascripts %} {{ encore_entry_script_tags('app') }}
{% endblock %}
</body>
</html>
If I use this, my profiler toolbar appear without icons
But if I remove {{ encore_entry_link_tags('app') }}
it start working again.
For instance, in my app.css I've tried to comment everything, without luck.
I just load font-awesome and bootstrap right now:
@import "~bootstrap";
@import "~@fortawesome/fontawesome-free/css/all.min.css";
And this is my app.js
/*
* 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 '../css/app.css';
// Need jQuery? Install it with "yarn add jquery", then uncomment to import it.
import $ from 'jquery';
global.$ = global.jQuery = $;
import 'bootstrap';
import 'popper.js';
import 'perfect-scrollbar';
import moment from 'moment';
global.moment = moment;
import 'bootstrap-switch';
When using the bundle in a long-running application server rendering multiple requests, we should register on the kernel.reset
tag so that the service resetter would reset the state of the lookup class (which already has the needed feature to allow resetting, but does not wire it in the service resetter)
Hi!
I am trying to use multiple Webpack configs in my webpack.config.json
. Following this guide — https://symfony.com/doc/current/frontend/encore/advanced-config.html — I've specified all builds inside webpack_encore.yaml
. And then I've tried to output my script(s) in my Twig template:
{{ encore_entry_script_tags('entry', null, 'build_name') }}
But I've got the following error:
An exception has been thrown during the rendering of a template ("Asset manifest file "/[path]/public/build/manifest.json" does not exist.").
Okay... but there is nothing about that neither in the docs nor in the webpack_encore.yaml
.
After some digging I've found assets.yaml
and that disabling assets.json_manifest_path
solves this issue and everything renders.
But I am still not sure — I do everything correctly or not. Maybe I have to specify builds (which are named "packages") inside assets.yaml
as well? And then:
{{ encore_entry_script_tags('entry', 'build_name', 'build_name') }}
But... I have to repeat the same parameter twice for some reason. And I have to specify my Webpack builds in several config files (under different keys).
It looks absolutely unintuitive. And there is a lack of information in the documentation about this.
P.S. I've found this: https://symfony.com/doc/current/frontend/encore/versioning.html
The first file - entrypoints.json - is used by the encore_entry_script_tags() and encore_entry_link_tags() Twig helpers.
The manifest.json file is only needed to get the versioned filename of other files [...] Be sure to wrap each path in the Twig asset() function like normal
I.e. entrypoints.json
for encore_entry_script_tags()
, and manifest.json
for asset()
? But I still do not understand why encore_entry_script_tags()
needs both parameters. If we can disable assets.json_manifest_path
in assets.yaml
and everything seems to work without it why does encore_entry_script_tags()
depend on both parameters? Why can't we make encore_entry_script_tags()
and asset()
dependent on the same unified parameter?
P.P.S. Honestly, in ideal world it would be great to specify builds only inside webpack.config.json
and then just use them in encore_entry_script_tags()
without adding them manually in several configs.
Summarizing:
Thank you! :)
I use "symfony/webpack-encore-bundle": "dev-master"
with symfony 5.0.5 and faced with strange problem, native js not working in my files... with silent error, nothign happened.. but some times, I not sure why it's appear, I had big data encoding to base64 in console DevTools failed to parse SourceMap: data:application/json;charset=utf-
and when I decode it it was a lot of text I will describe in in a boottom...
webpack.config.js
var 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
.setOutputPath('public/build/')
.setPublicPath('/build')
.addEntry('app', './assets/js/app.js')
.addEntry('index/js/index.min', './assets/js/index/index.js')
.addEntry('index/js/awin.min', './assets/js/index/awin.js')
.splitEntryChunks()
.disableSingleRuntimeChunk()
.cleanupOutputBeforeBuild()
.enableBuildNotifications()
.enableSourceMaps(!Encore.isProduction())
.enableVersioning(Encore.isProduction())
.configureBabelPresetEnv((config) => {
config.useBuiltIns = 'usage';
config.corejs = 3;
})
.enableSassLoader()
.addStyleEntry('index/css/index.min', './assets/css/app.scss')
.autoProvidejQuery()
;
module.exports = Encore.getWebpackConfig();
assets/js/app.js
import '../css/app.scss';
import * as dt_bs4 from 'datatables.net-bs4'
import * as fh_bs from 'datatables.net-fixedheader-bs4';
import * as r_bs from 'datatables.net-responsive-bs4';
require('@fortawesome/fontawesome-free/css/all.min.css');
require('datatables.net-dt/css/jquery.dataTables.min.css');
require('datatables.net-fixedheader-bs4/css/fixedHeader.bootstrap4.min.css');
require('datatables.net-responsive-bs4/css/responsive.bootstrap4.min.css');
require('@fortawesome/fontawesome-free/js/all.js');
const $ = require( 'jquery' );
global.$ = global.jQuery = $;
require('bootstrap');
templates/base.html.twig
{% block javascripts %}
{{ encore_entry_script_tags('app') }}
<script src="{{ asset('bundles/fosjsrouting/js/router.min.js') }}"></script>
<script src="{{ path('fos_js_routing_js', { callback: 'fos.Router.setData' }) }}"></script>
<script>
function getJSonObject(value) {
return $.parseJSON(value.replace(/"/ig, '"'));
}
let user_roles = getJSonObject("{{ app.user ? app.user.roles|json_encode() : "{}" }}");
</script>
{% endblock %}
and my twig which extend based and has js block too and where I exclude awin.min.js
{% block javascripts %}
{{ parent() }}
<script src="{{ asset('build/index/js/awin.min.js') }}"></script>
{% endblock %}
and finnaly my awin js file assets/js/index/awin.js
import list from './parts/sort.js';
document.addEventListener("DOMContentLoaded", function () {
list();
});
and assets/js/index/parts/sort.js
export default function list() {
console.log( "sort!" );
var text = 'test';
text = text.replace("text", "hello");
console.log(text);
}
and I checked runtime.js present in my html file
<script src="/build/runtime.js"></script><script src="/build/vendors~app~index/js/awin.min.js"></script><script src="/build/vendors~app.js"></script><script src="/build/app~index/css/index.min.js"></script><script src="/build/app.js"></script>
--
| <script src="/bundles/fosjsrouting/js/router.min.js"></script>
| <script src="/js/routing?callback=fos.Router.setData"></script>
and in that case I had empty colnsole in chrome and I made conclusion function list()
not executed.. it happend becasue I was use text.replace("text", "hello");
If I removed text.replace
operation from function list
assets/js/index/parts/sort.js
export default function list() {
console.log( "sort!" );
}
I faced with "sort!"
in console and made conclusion function list
executed.
But when I add text.replace
to assets/js/app.js
import '../css/app.scss';
import * as dt_bs4 from 'datatables.net-bs4'
import * as fh_bs from 'datatables.net-fixedheader-bs4';
import * as r_bs from 'datatables.net-responsive-bs4';
require('@fortawesome/fontawesome-free/css/all.min.css');
require('datatables.net-dt/css/jquery.dataTables.min.css');
require('datatables.net-fixedheader-bs4/css/fixedHeader.bootstrap4.min.css');
require('datatables.net-responsive-bs4/css/responsive.bootstrap4.min.css');
require('@fortawesome/fontawesome-free/js/all.js');
const $ = require( 'jquery' );
global.$ = global.jQuery = $;
require('bootstrap');
console.log( "app" );
var text = 'rrrr';
text = text.replace("lollypops", "marshmellows");
console.log(text);
and return back it in assets/js/index/parts/sort.js
export default function list() {
console.log( "sort!" );
var text = 'test';
text = text.replace("text", "hello");
console.log(text);
}
everything works. Looks like need call replace
function in app.js for correct working it in sort.js
...
and like I said before, this is example which appear time to time when replace
function present awin.js or sort.js file and not present in app.js
Ӣl}yhy*.njjZXjبw!j�_ڱ{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./assets/js/index/awin.js","webpack:///./assets/js/index/parts/sort.js"],"names":["document","addEventListener","console","log","text","replace","awinproductcollection","window","Routing","generate","common_defs","$","each","for_prepare_defs","key","value","inArray","data","img_columns","push","type","row","meta","link_columns","short_preview_columns","length","substr","list"],"mappings":"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","file":"index/js/awin.min.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tfunction webpackJsonpCallback(data) {\n \t\tvar chunkIds = data[0];\n \t\tvar moreModules = data[1];\n \t\tvar executeModules = data[2];\n\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(data);\n\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n\n \t\t// add entry modules from loaded chunk to deferred list\n \t\tdeferredModules.push.apply(deferredModules, executeModules || []);\n\n \t\t// run deferred modules when all chunks ready\n \t\treturn checkDeferredModules();\n \t};\n \tfunction checkDeferredModules() {\n \t\tvar result;\n \t\tfor(var i = 0; i < deferredModules.length; i++) {\n \t\t\tvar deferredModule = deferredModules[i];\n \t\t\tvar fulfilled = true;\n \t\t\tfor(var j = 1; j < deferredModule.length; j++) {\n \t\t\t\tvar depId = deferredModule[j];\n \t\t\t\tif(installedChunks[depId] !== 0) fulfilled = false;\n \t\t\t}\n \t\t\tif(fulfilled) {\n \t\t\t\tdeferredModules.splice(i--, 1);\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = deferredModule[0]);\n \t\t\t}\n \t\t}\n\n \t\treturn result;\n \t}\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// undefined = chunk not loaded, null = chunk preloaded/prefetched\n \t// Promise = chunk loading, 0 = chunk loaded\n \tvar installedChunks = {\n \t\t\"index/js/awin.min\": 0\n \t};\n\n \tvar deferredModules = [];\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__
I'm trying out multiple entrypoints, and first test was to define a single builds
directive:
webpack_encore:
builds:
frontend: '%kernel.project_dir%/web/build'
However, Webpack Encore complains that the output_path
is not configured: The child node "output_path" at path "webpack_encore" must be configured.
. Is this the intended behaviour? How would I go about specifying this kind of config as a starting point for other developers on my team to extend with more entrypoints?
When symfony/cache
is at version <=4.1.11
There was 1 error:
1) Symfony\WebpackEncoreBundle\Tests\IntegrationTest::testCacheWarmer
Undefined offset: 0
Here's my quickfix solution for it:
https://github.com/tszymanek/webpack-encore-bundle/blob/master/tests/IntegrationTest.php#L100
I bet it'd require changing composer require-dev
dependencies as well
Hello !
I just tried to install this new bundle coupled with the webpack-encore v0.21.0 and faced a little issue.
In my project we have multiple Encore configuration which export assets in multiple output path. Maybe it's not the recommended way to use it but with that setup I can't use the new features because every call to twig functions will read the entry point defined in the output path.
Before that, we used the asset package feature to declare multiple packages (each one with it's own manifest.json file).
I checked the Bundle code and find that the asset packages are still used but the entrypoint.json file is always the same.
Is there a way to handle that case ?
This #13 issue is implemented. It solves problem which happens while using multiple Encore configurations. Now it is possible to specify as much builds as we want. But it solves "multiple configurations" problem only for CSS and JS files.
I'm using Encore.copyFiles()
to copy my static files (images, videos, etc). Documentation says that we need to use asset
component which uses json_manifest_path
. And there is no option to specify multiple manifests.
So maybe it would be a nice idea to add something like ManifestLookup
and encore_asset
function that will resolve path to the static files for us.
{{ encore_asset('images/top.jpg', 'landing') }}
{# Will print /builds/landing/images/top.hash.jpg #}
你能不能开发些能用的东西,这个东西实在难用,每天都会出错。
Hello @weaverryan,
I have this theme system, and would like to add a build based on the theme name with the path, is it possible to configure the build dynamically without adding it in the webpack_encore.yml configuration? That is, the same thing you do with the packages.
I have been doing some research and I have seen that all the configuration is inside the container, do you know how I could modify this?
Thanks
After update I've got:
[Symfony\WebpackEncoreBundle\Exception\EntrypointNotFoundException]
Could not find the entry "dummy" in "/source/public/build/entrypoints.json". Found: entrypoints.
There is indeed catch for EntrypointNotFoundException
in EntrypointCacheWarmer
but it refers to ymfony\WebpackEncoreBundle\CacheWarmer\EntrypointNotFoundException
which does not exist (or my IDE is wrong) but Symfony\WebpackEncoreBundle\Exception\EntrypointNotFoundException
exist and is thrown. I assume that use
is missing.
EDIT:
I tested it on fresh install and problem exist there too.
Symfony version(s) affected: 4.2
Description
The EntrypointLookup
prevents including a file multiple times by default. But it prevents re-using a stylesheet in an error template if an error occurs during the rendering of a template that re-uses the layout. This is because the ExceptionController
will clear the output buffers.
How to reproduce
{{ 1 / 0 }}
Possible Solution
The EntryPointLookup
class must only return a template once per request.
Hello,
I am trying to get the css files of an entry to then pass them to a javascript that builds an iframe and adds in the iframe the css files.
I am adding EntrypointLookupInterface
as a dependency and call getCssFiles
of an entry that I have declared in webpack.config.js
. The problem is that the function getCssFiles
calls getEntryFiles
that filters already returned files, resulting that some common files are not added then in my website when I call in twig {{ encore_entry_link_tags }}
.
Looking at the code I cannot see any way to get the files avoiding this filtering.
There could be another function to retrieve entries without filtering, or add a parameter to getCssFiles
and getJsFiles
to skip filtering.
In some cases, you may want to use a different implementation of reading the entrypoint data (I've talked with someone about a use-case). So, we should:
Currently, the bundle performs de-duplication of the returned files. This is useful to avoid rendering the same <script>
tag multiple times. But it makes it harder to render <link rel="preload">
in the <head>
and then <script>
at the end of the body (as here, we precisely need to get the full list twice).
The way to do it currently would be to call encore_entry_js_files
and store the result in a variable used in both places. But this is not convenient at all. The variable must be defined in a scope higher than both places needing it, and it is very common to have a block wrapping the <script>
tags to make it handy for child templates to add more, but blocks create a new scope and so mutating the array inside the block has no effect outside it. It is also quite fragile in case the variable name is used elsewhere in the template (as the head and the end of the body are at opposite sides of the rendering of the template).
With the new Symfony Mime Component, in Symfony 4.3 experimental, it becomes accepted practice to make e-Mails with Twig. E-Mails require inline CSS, which is achieved thanks to an inline_css filter. Is there a recommended way on how to use webpack encore generated assets with the inline_css
filter?
I see two possibilities as for the current possibilities (am I missing one, is one coming ahead?):
inline_css(source(encore_entry_css_files("my-email-entry")|first))
{ filter inline_css }
without opening the source, and dumping the source ourselfs into a <style>
inside the filter. This way, we can have the loop {% for css_loc in encore_entry_css_files("my-email-entry") %}{{ source("@myBuildNamespace" ~ css_loc) }}{% endfor %}
and therefore more than one output file. This case would be a further use case for #16Best regards
Can you release a new tag, please? As multiple entrypoints
is the quite important feature
There are a few legit use-cases for wanting to use the encore_entry_script_tags()
functions, but pass a custom attribute:
integrity
attributepreload
, async
, etcAnother attribute, in theory, would be adding data-
attribute on your script tag. But, that doesn't make sense with encore_entry_script_tags()
, because this could render multiple script tags.
I think the main use-cases then are the ones in the list above. And, these might be best integrated (especially integrity
) with some global option. I'd like to get use-case feedback and use that to motivate how this is designed.
Hi,
My error pages are overridden with Twig, using the templates/bundles/TwigBundle/Exception/error.html.twig
template. In this template, I use the encore_entry_link_tags()
function and encore_entry_script_tags()
function.
The problem is that sometimes the 500 error pages in prod env do not have any stylesheets/scripts loaded as the related tags are not rendered.
I managed to make a reproducer: https://github.com/jmsche/webpack-encore-bundle-reproducer
I think the issue is when something during template rendering fails. Eg. here the following line will trigger an exception as no "test" entry exists: https://github.com/jmsche/webpack-encore-bundle-reproducer/blob/master/templates/500.html.twig#L4
IIUC the problem is in fact here: https://github.com/symfony/webpack-encore-bundle/blob/master/src/Asset/EntrypointLookup.php#L73
As the assets were previously loaded, they won't be for the error template.
Symfony version(s) affected: 5
Description
Attempted to load class "GenericLinkProvider" from namespace "Fig\Link". Did you forget a "use" statement for "Symfony\Component\WebLink\GenericLinkProvider"
How to reproduce
create new project symfony/skeleton
composer req encore
activate preload
webpack_encore:
preload: true
in config/package/webpack_encore.yaml
composer req web-link
as requested by the bundle
Possible Solution
change namespace from Fig\Link
to Symfony\Component\WebLink
in Symfony\WebpackEncoreBundle\EventListener\PreLoadAssetsEventListener
I am having troubles after installing webpack-encore-bundle with those two packages :
After setting up them, I am having this error message :
Uncaught PHP Exception Twig\Error\RuntimeError: "An exception has been thrown during the rendering of a template ("Warning: htmlentities(): charset `�' not supported, assuming utf-8")."
The only one solution I found was to edit :
vendor/symfony/webpack-encore-bundle/src/Asset/TagRenderer.php:L:149
Replace :
return sprintf('%s="%s"', $key, htmlentities($value));
By this :
return sprintf('%s="%s"', $key, htmlentities($value, ENT_QUOTES, 'utf-8'));
I found that https://github.com/symfony/webpack-encore-bundle/blob/master/src/Asset/EntrypointLookup.php#L84-L87
causes 1+N request to don't have assets.
This is my use case:
I have several private page that I need to export as PDF.
Because they are private (needs authentication) - I make several forward request to get generated HTML.
And then pass the generated HTML to service that generates PDF from HTML.
But all pages after first one have broken styles.
What about option to inline assets (CSS or JS) into twig?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.