webpack: How to inject the JS chunks in the a YAML file - javascript

I'm using webpack to modernize a legacy MVC application (symfony 1.4)
I would like to inject the JS chunks and the CSS file in a YAML file that contains several other settings.
Here is an example:
default:
foo: bar
.
.
stylesheets: [ style.db80006f5e14f38456ef.css ]
javascripts: [ runtime.d8969ec83f67a36c8877.js, npm.material.db07856eff6817abe7f2.js, main.db80006f5e14f38456ef.js ]
.
.
The html-webpack-plugin supports plugin as well. I was wondering if it would be possible with my own plugin for the html-webpack-plugin to inject the CSS files and JS files in a YAML file instead of an HTML template. I'm not sure if the html-webpack-plugin is the way to go since I don't want to manipulate an HTML file.
Maybe there is another possibility to get the names and the order of the JS chunks, plus the CSS file.
Thanks a lot in advance!

html-webpack-plugin is the way to go, you can provide your "base" yaml file as a template, and provide a templateContent function that will generate your yaml content.
Something like this:
new HtmlWebpackPlugin({
templateContent: function(params) {
return `
default:
stylesheets: [ ${params.htmlWebpackPlugin.files.css.join(',')} ]
javascripts: [ ${params.htmlWebpackPlugin.files.js.join(',')} ]
`;
},
filename: 'path-to/where/to/save/your.yaml',
inject: false, // prevents from the plugin to auto-inject html tags
});

Related

precaching a generated asset in Service Worker

I have some resources which are getting generated on runtime or on build for example scripts, CSS, etc.
The file format is something like this main.min.63716273681.js and similarly for other resources as well.
Unfortunately, I cannot use sw-precache library or anything integrated with my build.
How can I precache those resources, Is it possible to do it using regex?
Note: The question is about precaching the resource and resources are getting generated by AEM(Adobe experience manager)
install webpack-manifest-plugin and import at the top of your webpack config file
const ManifestPlugin = require('webpack-manifest-plugin');
use the below code in your webpack plugin section this will generate a file name asset-manifest.json with all the assets that are build by webpack
new ManifestPlugin({
fileName: 'asset-manifest.json',
publicPath: your public path here,
}),
it will generate file having content like below
// asset-manifest.json
{
"files": {
"about.js": "/static/js/about.bc816d03.chunk.js",
"about.js.map": "/static/js/about.bc816d03.chunk.js.map",
"dashboard.js": "/static/js/dashboard.f180c270.chunk.js",
"dashboard.js.map": "/static/js/dashboard.f180c270.chunk.js.map",
"homepage.js": "/static/js/homepage.4dd0316c.chunk.js",
"homepage.js.map": "/static/js/homepage.4dd0316c.chunk.js.map",
"login.js": "/static/js/login.1b8cf466.chunk.js",
"login.js.map": "/static/js/login.1b8cf466.chunk.js.map",
"logout.js": "/static/js/logout.ac3c5758.chunk.js",
"logout.js.map": "/static/js/logout.ac3c5758.chunk.js.map",
"main.css": "/static/css/main.977b6895.chunk.css",
"main.js": "/static/js/main.a65a1d5d.chunk.js",
"main.js.map": "/static/js/main.a65a1d5d.chunk.js.map",
"profile.js": "/static/js/profile.20ae3dae.chunk.js",
"profile.js.map": "/static/js/profile.20ae3dae.chunk.js.map",
"runtime-main.js": "/static/js/runtime-main.ad8b0a50.js",
"runtime-main.js.map": "/static/js/runtime-main.ad8b0a50.js.map",
"static/js/8.796ce7e3.chunk.js": "/static/js/8.796ce7e3.chunk.js",
"static/js/8.796ce7e3.chunk.js.map": "/static/js/8.796ce7e3.chunk.js.map",
"index.html": "/index.html",
"precache-manifest.e770a629726af82e25b547dd941bae89.js": "/precache-manifest.e770a629726af82e25b547dd941bae89.js",
"service-worker.js": "/service-worker.js",
"static/css/main.977b6895.chunk.css.map": "/static/css/main.977b6895.chunk.css.map",
"static/js/8.796ce7e3.chunk.js.LICENSE.txt": "/static/js/8.796ce7e3.chunk.js.LICENSE.txt",
"static/media/arvidsson.jpg": "/static/media/arvidsson.4d6f8e0d.jpg",
"static/media/logo.jpg": "/static/media/logo.8caa15b8.jpg",
"static/media/pekka.jpg": "/static/media/pekka.1eab475c.jpg"
},
"entrypoints": [
"static/js/runtime-main.ad8b0a50.js",
"static/js/8.796ce7e3.chunk.js",
"static/css/main.977b6895.chunk.css",
"static/js/main.a65a1d5d.chunk.js"
]
}
you can read asset-manifest.json file and take the files object and iterate and check the key having .js in the end.
Hope this will answer your question.

How to inject Webpack DefinePlugin variables in non Module Scripts

I have the following issue:
I'm using the DefinePlugin to define some variables across .js modules. This is working fine in .js modules
However, my multi page application loads a local script (custom.js) inside a <HEADER> TAG. This script is standard javascript (not a module), using one of the variables defined in DefinePlugin. It's a .js that must be loaded in every page of the App.
For some reason this variable WEB_CONTEXT is not being interpolated by Webpack on BUILD process.
I assume that the reason is that as it is not recognized as a dependency.
Webpack config.js:
new webpack.DefinePlugin({
'WEB_CONTEXT': 'myapp/main'
);
The global script is loaded like this:
<script src="./src/js/custom.js"></script>
custom.js
$(function () {
// Compiled file incorrectly shows:
const myPath = `${WEB_CONTEXT}/resources/images`;
// Instead of:
const myPath = `myapp/main/resources/images`;
});
});
Question is:
Is there anyway with Webpack to make WEB_CONTEXT variable available ALSO for those scripts like custom.js (not imported, but loaded via ?
Webpack "works" only on files that are part of the dependency tree that starts from the entry file.
If your custom.js file is not inside this tree, webpack won't touch it.
You can add it by require it, or add it as additional entry to your app.
//webpack.config.js
module.exports = {
entry: {
main: './path/to/my/entry/file.js',
custom: './path/to/custom.js'
}
};
webpack.config.js
entry : {
main: './path/to/my/entry/file.js',
custom: './path/to/custom.js'
}
And the in the plugins section:
new HtmlWebpackPlugin({
template: `./${ruta}`,
inject: true,
chunks: ['main', 'custom'], // <-Added custom chunk here.
filename: `${fileName}.html`,
templateParameters: {
WEB_CONTEXT: basePath
}
});

How to stop purging tailwind components

I am using TailwindCSS and Laravel Mix. I am trying to setup PurgeCSS and I have got it reading my template files (working with WordPress) and purge any CSS not within the template files.
However, as part of Tailwind, I am using #apply in my scss files and those utilities I am applying are also being purged which leaves me with a non functioning site.
My sass files are in css/dev and there is an app.scss and then directories with more files within them (base, utilities, custom, components).
My webpack.mix.js file configuration is as follows:
mix.scripts(['js/dev/app.js', 'js/dev/navigation.js', 'js/dev/skip-link-focus-fix.js'],
'js/build/app.js')
.sass('css/dev/app.scss', 'css/build')
.options({
processCssUrls: false,
postCss: [tailwindcss('./tailwind.config.js')],
})
.purgeCss({
enabled: mix.inProduction(),
// Your custom globs are merged with the default globs. If you need to
// fully replace the globs, use the underlying `paths` option instead.
globs: [
path.join(__dirname, 'template-parts/*.php'),
path.join(__dirname, '*.php'),
path.join(__dirname, 'css/dev/*.scss'),
path.join(__dirname, 'css/dev/**/*.scss'),
],
extensions: ['html', 'js', 'php', 'scss', 'css'],
});
As you can see, I tried setting the paths for purgeCss to look inside the css paths but that has not worked.
Does anyone know how to achieve this?
You are compiling your scss to css before Purge runs, so there should be no need to purge your .scss files only your main.css (or whatever the output is called).
Do your compiled class names actually exist in full in your template files? If they are not a 100% match for the classes in your templates then they will, quite correctly, be purged.
The issue was with WordPress classes not being included in the template files and then being purged. The solution was switching to using UnCSS which allowed me to setup URLS for UnCSS to visit and it won't purge any classes used on those pages. I also included some standard WordPress classes which I found a list of online.
My final config is:
const uncss = require('postcss-uncss');
mix.js('js/dev/app.js', 'js/build/app.js')
.sass('css/dev/app.scss', 'css/build')
.options({
processCssUrls: false,
postCss: [
tailwindcss('./tailwind.config.js'),
...process.env.NODE_ENV === 'production' ? [uncss({
html: [
'./*.php',
'./template-parts/*.php',
'https://www.example.com',
'https://www.example.com/work/',
'https://www.example.com/work/example-project/',
'https://www.example.com/contact/',
'https://www.example.com/blog/',
'https://www.example.com/blog/laravel-php-framework/',
],
ignore: [
'.rtl',
'.home',
'.blog',
'.archive',
'.date',
'.error404',
'.logged-in',
'.admin-bar',
'.no-customize-support',
'.custom-background',
'.wp-custom-logo',
'.alignnone',
'.alignright',
'.alignleft',
'.wp-caption',
'.wp-caption-text',
'.screen-reader-text',
'.comment-list',
'.grecaptcha-badge',
/^search(-.*)?$/,
/^(.*)-template(-.*)?$/,
/^(.*)?-?single(-.*)?$/,
/^postid-(.*)?$/,
/^attachmentid-(.*)?$/,
/^attachment(-.*)?$/,
/^page(-.*)?$/,
/^(post-type-)?archive(-.*)?$/,
/^author(-.*)?$/,
/^category(-.*)?$/,
/^tag(-.*)?$/,
/^tax-(.*)?$/,
/^term-(.*)?$/,
/^(.*)?-?paged(-.*)?$/,
'.animate',
'.animated',
'.bounce',
'.fadeInDown',
'.fadeIn',
'.fadeInUp',
'.jackInTheBox',
]
})] : [],
]
});
I also made use of the UnCSS exclude from purge CSS comments:
/* uncss:ignore start */
my css goes here
/* uncss:ignore end */
I ended up using this on all my custom sass files except for the tailwind files so that the only selectors that are purged are tailwind utilities, which saved me about 300 KB.

Webpack to simply compile a bunch of Pug templates to HTML

Im getting started with webpack but one thing I cannot for the life of me work out is how to take a folder (with possible nested folders), full of .pug templates, and simply compile them to static html and put them in the output folder, maintaining any nested folder structure for each output html file that was in the source templates folder...
I dont want to have to manually specify each individual .pug file, and I definitely dont want webpack to try and parse the .pugs into JS and then attempt to require/import any of the imgs/fonts etc in the pug files and then complain about it, Im just after a basic, static 1:1 compile, pug file in, html file out. Why is it so hard to do that?
Use pug-html-loader to convert .pug to .html file. Use file-loader to copy the file to desired location. Don't use html-loader as you don't want to process resources used by the generated file.
You will end up something like this in your loader rules (untested, webpack 1 syntax, you may need to tweak it for webpack 2)
{
test: /\.pug$/,
loaders: ['file-loader?name=[path][name].html', 'pug-html-loader?pretty&exports=false']
}
Next you need to require all your pug files in your entry file
function requireAll (r) { r.keys().forEach(r); }
requireAll(require.context('./', true, /\.pug$/));
This can be done very simply with only html-webpack-plugin and pug-loader.
webpack.config.js
const HTMLWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// No javascript entrypoint to evaluate. Let the plugin do the heavy lifting
entry: {},
// Translate Pug to HTML
module: { rules: [ { test: /\.pug$/, use: 'pug-loader' } ] },
// Save HTML to file
plugins: [ new HTMLWebpackPlugin({ template: './src/index.pug' }) ]
};
./src/index.pug
doctype html
html(land="en")
head
include path/to/another.pug
...
Got this information from https://extri.co/2017/05/23/using-htmlwebpackplugin-and-pug/ and you can also go further to import css and javascript as normally done with html-webpack-plugin.

Webpack: Loading external JSON without bundling

I'm building my first one-page site using redux + deku and I need to internationalize it. I want to have a json file with all the texts, something like this:
# http://mysite.me/assets/i18n.json
{
"en": {
"greeting": "Hello"
},
"es": {
"greeting": "Hola"
}
}
Ideally I can require it in my boot file:
const T = require('/assets/i18n.json')
setTranslation(T)
But it mustn't be bundled in the same file, it should remain an external dependencies and it should load at runtime, so that I can edit it without needing to recompile the entire app!
Is it possible with webpack? Is my only option to include it directly in the HTML?
<script type="text/javascript" src="i18n.js"></script>
<script type="text/javascript" src="app.js"></script>
For now this last solution is ok, but I was thinking on splitting the translations per main components, therefore the ability to include it directly through js would be nice.
Thanks to anyone who will help :)
One option would either to not require the file but instead fetch (or some other request method) and then exclude JSON from webpack.
The other way would be to split the code using the common chunks plugin for webpack. Your webpack config would look something like this:
entry: {
app: './index.jsx',
i18n: [
'en',
'fr',
'...others'
]
},
output: {
path: '/path/to/dist/',
filename: '[name].js'
}
See the official docs for more information

Categories

Resources