I'm struggling to find a "quick" way to transition some legacy javascript files from assetic to webpack. I (think I) need to find a way to bundle a set of javascript files by simply concatenating them and not having webpack wrap it in a jsonp.
Our platform is built in Symfony, using twig templates and we've got most of our legacy javascript files loaded using assetic (it simply concatenates, and minifies), we've got newer javascript/typescript files bundled with webpack.
Naturally I want to remove all assetic dependencies and use webpack to bundle the old javascript. However, due to the way that webpack produces the bundles, it gets wrapped in the jsonp and any functions/variables defined in those javascript files are not available in global scope.
In an assetic world, our twig files are littered with these:
{%- javascripts
'%kernel.root_dir%/../vendor/twbs/bootstrap/js/bootstrap-transition.js'
'@MyBundle/Resources/js/legacy-1.js'
'@MyBundle/Resources/js/legacy-2.js'
filter="?uglifyjs2"
output="js/compiled/page-one.js" %}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
Which concatenates and minifies them all. I'd like to replace this with a similar webpack version.
I've identified some approaches, but I'm not sure any of them are the best.
- Use
script-loader
to get the scripts to load in global scope - Sincescript-loader
useseval
which is disabled using CSP, this is out of the question - Rewrite each javascript file, exposing the members on the window. - This would probably be the easiest option but I really don't like the idea, and it goes against best practices.
- Rewrite each javascript file, exporting the members, then use the
expose-loader
to load the files, then go through all the twig files and update the references to the members with the global namespace. This would take a lot of time, and I'd prefer not to do this if at all possible
I figured that I could simply configure a queryParameter and the file-loader
to load each one, but I'd need a script tag per resource, and would lose out on the bundling nature. (I use a Symfony webpack bundle to generate an entries
list for webpack, and provide twig functions for loading entries at runtime from the cdn)
<script src='{{ webpack_asset('%kernel.root_dir%/../vendor/twbs/bootstrap/js/bootstrap-transition.js?asFile') }}"></script>
<script src='{{ webpack_asset('@MyBundle/Resources/js/legacy-1.js?asFile') }}"></script>
<script src='{{ webpack_asset('@MyBundle/Resources/js/legacy-2.js?asFile') }}"></script>
So I'm looking for a way to concatenate the files together. Creating a separate entry file, and loading that as a file wouldn't be good enough as the require
s/import
s wouldn't be resolved.
I understand the webpack-concat-plugin
would require me to define all of the various files to concat up front in the webpack config, which isn't really possible.
I haven't come across a loader that would replace the import '@MyBundle/Resources/js/legacy-2.js'
with the content of that js file - but maybe I'm missing something.
I wonder if after all of this effort trying to find an easy solution is greater than the effort to rewrite the legacy javascript to use modules...
I found the following answers but they don't really help me:
- Webpack - How to load non module scripts into global scope | window - This assumes I can define the files to concatenate up front. I have almost 100 different includes using assetic, almost all of them use different files.
- Webpack - How to load non module scripts into global scope | window -
eval
is disabled by our CSP - Expose javascript globals bundled via webpack - As I mentioned, I don't really want to create 100 'entry' files just for this, and the
webpack-raw-bundler
also requires everything to be defined up front in the webpack config file.