nystudio107 / craft-twigpack Goto Github PK
View Code? Open in Web Editor NEWTwigpack is a bridge between Twig and webpack, with manifest.json & webpack-dev-server HMR support
Home Page: https://nystudio107.com/
License: MIT License
Twigpack is a bridge between Twig and webpack, with manifest.json & webpack-dev-server HMR support
Home Page: https://nystudio107.com/
License: MIT License
Hi,
When I use webpack-dev-server I'm using the style-loader
instead of the MiniCssExtractPlugin.loader
so my styles are also Hot reloaded. But it also means it doesn't output a css file. In my base layout I have the following line:
{{ craft.twigpack.includeCssModule("index.css") }}
which normally points to an extracted css file from index.js, but in dev-server mode it's missing from the manifest. Any idea how to handle this?
Hey Andrew,
I see that this plugin works in regards to prefetching/loading the entry points, but was curious how you handle prefetching/loading of dynamic imports(lazy components) js and css.
Vue Cli extracts all the CSS and by default will create prefetch/preload links, but haven't found the best practice for including these. For now we've turn the extraction of CSS off but was curious what a best practice is here and how Twig Pack could help us out.
Does Twigpack support accepting self-signed certificates in devMode? It seems if I set the devServer URLs to https://localhost:8080/
instead of http://localhost:8080/
scripts aren't included via the JS tag ({{ craft.twigpack.includeJsModule("app.js") }}
).
If it's not currently supported, would you consider adding it as an option when in devMode?
I have app.css going into manifest.json, but I get Module does not exist in the manifest: app.css
If I switch it over to manifest-legacy.json
it reads it correctly.
I believe the example should say:
{{ craft.twigpack.getModuleUri("app.js") }}
not
{{ craft.twigpack.getModule("app.js") }}
Hi,
Wondering if a stable release for Craft 4 is planned to be released soon ?
Thanks
In the docs there is a use case of the alias @webroot
'server' => [
'manifestPath' => '@webroot/',
'publicPath' => '/',
],
Steps to reproduce the behaviour:
'@webroot'
@webroot alias should be converted so the path is correct ( Craft::getAlias('@webroot') )
This is a question about hashes or maybe about cache. I'm making a regular craft website with a few vue components.
When I do npm run build, everything works great locally. But when I push to the production site, which is on a shared host, the CSS and JS in dist/ is linked incorrectly. The links are there in the html, but the hashes are all wrong. I tried clearing the craft cache, but that did nothing. I have no idea where these original hashes are from anyway – I don't understand how the production site even knows about these files, which no longer exist. The dist/manifest.json gets pushed to production and has the right hashes, but these are not being used.
Does anyone know why this is? Am I missing something stupid?
To get around this for the moment: I turned off filenameHashing
in vue.config.js. Then in _layout.twig, I took out craft.twigpack.includeCssModule("app.css", true)
and craft.twigpack.includeJsModule("app.js", true)
and instead wrote the links to the unhashed files manually. I assume this will cause caching problems later on, but I couldn't get anything else to work.
Thanks for any ideas.
Our manifest.json
and webapp.html
files are being generated as expected, and a reference to the webapp.html
file is in the manifest -
"webapp.html": "/assets/bundled/webapp.html"
All the paths and file contents look correct, but {{ craft.twigpack.includeFileFromManifest("webapp.html") }}
isn't inserting any markup. This has been working correctly up until recently and we haven't changed anything in the build setup, so think it must be a recent update?
Craft version 3.3.11
Twigpack version 1.1.11
Nothing to add, if using {{ craft.twigpack.includeCssModule("app.css", true) }}
the fallback doesn’t seem to work in Firefox (v69.0b16).
Hi, Will there be a Craft 5 version of this plugin. Wondering since Craf 4 version is still in beta.
I have a manifest file sitting at http://localhost:8080/build/manifest.json
and I configured my twigpack.php as follows:
// Manifest file names
'manifest' => [
'legacy' => 'manifest-legacy.json',
'modern' => 'manifest.json',
],
// Public server config
'server' => [
'manifestPath' => '/build/',
'publicPath' => '/',
],
// webpack-dev-server config
'devServer' => [
'manifestPath' => 'http://localhost:8080/build/',
'publicPath' => 'http://localhost:8080',
],
However, twigpack can't find my modules it seems. and doesn't output anything. Is there a way for me to debug this, whether Twigpack found the manifest at all?
EDIT:
I went through my logs and indeed, Twigpack can't find the file.
[warning][nystudio107\twigpack\helpers\Manifest::reportError] Manifest file not found at: http://localhost:8080/build/
Any idea what I'm doing wrong?
Right now I have to switch:
'server' => [
'manifestPath' => 'http://localhost:8080/',
'publicPath' => '/',
],
to
'server' => [
'manifestPath' => '/_compiled/',
'publicPath' => '/',
],
and set useDevServer
to false
'local' => [
'useDevServer' => false,
],
in order to view the compiled files. Is there an eaiser way to set this up? It would be great if we knew if the devserver was running.
Hi there,
I recently purchased a license, all seems to be working great, thanks!
I'm configuring my Content-Security-Policy headers and am looking to enable strict-dynamic
, which would require nonce
attributes on my outputted script/style tags.
Is there any way I can achieve this?
ie:
Current input:
{{ craft.twigpack.includeCriticalCssTags() }}
{{ craft.twigpack.includeSafariNomoduleFix() }}
Current output:
<style>.styles{}</style>
<script>
!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();
</script>
Desired output:
<style nonce="mynoncehash1">.styles{}</style>
<script nonce="mynoncehash2">
!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();
</script>
Maybe just a way to access the script or style tag contents directly would do, rather than the script/style tag html markup around it.
Thanks 🙏
*Edit: Apologies my previous example was complete garbage. Baby brain.
Styles are working locally, but the cache is not breaking certain styles when running my build task. This isn't affecting all areas, just one section of the css. I've tried changing the class names, moving that scss module file etc, but the minified css file is still showing the old styles. It's strange because as I'm adding new styles elsewhere, the build is tracking those. Any ideas here?
Multiple calls to craft.twigpack.getModuleUri()
in a template cause the contents of the manifest file to be read on each call. Each content reading causes a GuzzleHttp request with a delay that builds up as the template is rendered.
The commit b4f2c34 "Add a 100ms delay when requesting the manifest file..." effectively adds a delay in reading the manifest content but if hot mode is enabled and devserver is not running, it causes a cascading delay when rendering the template (more than 5 seconds in a typically 200ms template).
twigpack.php
, set 'useDevServer' => true
and enable devMode in craft config.craft.twigpack.getModuleUri
multiple times (i'm loading optimized versioned svg and images from the manifest file in this way)The rendering of the page should not be slow.
The content of the manifest file should be read only once and its content should be cached for at least the current request, so a delay of 100ms would be acceptable.
I'm pretty sure this is nothing Twigpack is doing wrong, but logging here in case someone else runs into the same thing.
To clear caches on deploy, you would run a script or command on release, eg this in your Procfile
:
release: ./craft clear-caches/data
That runs, and runs successfully, but I end up with broken assets until I manually run it again.
I suspect what is happening is the command is in fact clearing the cache, but then a subsequent incoming request re-caches (the old) assets, before the deploy is fully complete.
So, I'm trying to see if there is some "post-successful deploy" thing for Heroku.
FWIW, I'm also trying dev-develop
, as the FileDependency stuff might help here when things get out of sync.
{{ craft.twigpack.includeCriticalCssTags() }}
always returns empty, even though my twigpack.php
file is configured properly with the correct 'localFiles'
values. The respective critical css files also exist.
I tried to directly pass in the path to the critical css file like this, but it still doesn't work: includeCriticalCssTags("mypath/index_critical.min.css")
craft.twigpack.includeInlineCssTags(mypath/index_critical.min.css)
, however, does work, so I can't identify the source of the problem.
Running Craft 3.4.25, Twigpack 1.2.3.
support the inclusion of the related chunks created with webpack chunks: 'all'
chunks-webpack-plugin manifest output example:
{
"app": {
"styles": [
"/sample.com.au/dist/css/app.1dd06925.css"
],
"scripts": [
"/sample.com.au/dist/js/0.3405942a.js",
"/sample.com.au/dist/js/1.ff95e12d.js",
"/sample.com.au/dist/js/app.1dd06925.js"
]
},
"product": {
"styles": [],
"scripts": [
"/sample.com.au/dist/js/0.3405942a.js",
"/sample.com.au/dist/js/product.1f565b46.js"
]
}
}
include a function along side: {{ craft.twigpack.includeJsModule("app.js") }}
could be {{ craft.twigpack.includeJsModules(["app","product"]) }} with array of modlue names, then strip duplicated paths and output in order script tags.
true multi page shared chunks.
Also include the style option, in addition to {{ craft.twigpack.includeCssModule("app.css", false) }} include a {{ craft.twigpack.includeCssModules(["app","products") }} same functionality as JsModules for styles.
adding new function for backwards compat.
If I have a multisite environment, such as site.test
and site.test/jp
, Twigpack creates the URL for the manifest file using the full siteUrl
, such that what would normally be http://site.test/assets/css/app.css?id=31b936e9b9364486cabb
is now http://site.test/jp/assets/css/app.css?id=31b936e9b9364486cabb
. Is there a config override for this or some way to alias the language/site url to point to the original file?
I've taken at how how I think this function should work, but I have two main concerns:
public static function getFileFromManifest(array $config, string $fileName, string $type = 'legacy'): string
{
$path = null;
try {
$path = self::getModuleEntry($config, $fileName, $type, true);
} catch (NotFoundHttpException $e) {
Craft::error($e->getMessage(), __METHOD__);
}
if ($path !== null) {
// Let's try and get a built file first
$localPrefix = $config['localFiles']['basePath'] . $config['localFiles']['criticalPrefix'];
$localPath = self::combinePaths(
$localPrefix,
$path
);
$alias = Craft::getAlias($localPath, false);
if ($alias && is_string($alias)) {
$localPath = $alias;
}
if (is_file($localPath)) {
return self::getFile($localPath) ?? '';
}
// If that failed, maybe it's available from the webpack-dev-server
$devServerPrefix = $config['devServer']['publicPath'];
$devServerPath = self::combinePaths(
$devServerPrefix,
$path
);
return self::getFileFromUri($devServerPath, null) ?? '';
}
return '';
}
Hello,
We just got HMR working with Twigpack - great! However, the built CSS link isn't being added to the page.
When running Webpack Dev Server the following tag results in the CSS link being added to the page:
{{ craft.twigpack.includeCssModule("main.css") }}
However, when building the files, this same tag results in no CSS link being rendered.
I was originally thinking there was some configuration issue in twigpack.php
- but I've just tested the following tag and it outputs the location to the CSS:
{{ craft.twigpack.getModuleUri("main.css") }}
Therefore this demonstrates that Twigpack can successfully find the manifest.json
file and get the path to main.css
.
A temporary work around is the following, but not ideal:
{% set cssURL = craft.twigpack.getModuleUri("main.css") %}
{% css cssURL %}
The relevant bit of twigpack.php
:
'server' => [
'manifestPath' => 'https://siteurl.site/assets/',
'publicPath' => 'https://siteurl.site/',
],
// webpack-dev-server config
'devServer' => [
'manifestPath' => 'http://localhost:8081/assets/',
'publicPath' => 'http://localhost:8081/',
],
When running the Webpack build, this results in the CSS being created in web/assets/css
and manifest.json
being created in web/assets
. Here is the contents of the manifest.json
:
{
"main.css": "/assets/css/main.css"
}
Any help appreciated!
Hey Andrew,
Seeing some odd behaviour in the latest version (v1.1.5), where when using the includeJsModule function like this:
{{ craft.twigpack.includeJsModule("app.js", true) }}
.. so, it doesn't seem to be getting the most recent file reference from the manifest.json
for the modern JS bundle, but it is getting the correct reference to the legacy JS bundle from the manifest-legacy.json
file, and the CSS reference further up the page is also working correctly as well. (can provide test urls if needed)
Have tried clearing all the caches, deleting runtime folders, redeploying, restarting, etc etc..
Hello,
In the helpers\Manifest::getModule
function the static const $isHot is used but without properly set.
I've created a PR for that. If you could merge it when you've got a chance that would be great.
Thanks.
When I install this plugin I get an unknown error and the config is dumped in the page:
This is my ./config/twigpack.php:
return [
'*' => [
'useDevServer' => false,
'manifest' => [
'legacy' => 'manifest.json',
'modern' => 'manifest.json',
],
'server' => [
'manifestPath' => '/',
'publicPath' => '/',
],
'devServer' => [
'manifestPath' => 'http://localhost:8080/',
'publicPath' => 'http://localhost:8080/',
],
],
'production' => [
],
'staging' => [
],
'dev' => [
'useDevServer' => false,
],
];
PHP version | 7.2.10 |
MySQL | 8.0.12 |
Craft version | Craft Solo 3.0.25 |
Twigpack | 1.0.2 |
We have experienced an extremely weird case with craft-twigpack not being able to connect with the webpack-dev-server properly.
During the craft-twigpack initialization there is a request to webpack-dev-server like so:
GET http://localhost:8080/mix-manifest.json
User-Agent: User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13
Accept: */*
Clearly this is not a valid HTTP request.
Steps to reproduce the behaviour:
This should be easily seen with a tcpflow
:
$ sudo tcpflow -c -i any host localhost and port 8080
Request to the webpack should be a well-formed HTTP request:
GET http://localhost:8080/mix-manifest.json
User-Agent: User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13
Accept: */*
We couldn't get craft-twigpack to work with our docker-compose setup. We've went through a debug session and found out a root cause of the issue:
https://github.com/nystudio107/craft-twigpack/blob/v1/src/helpers/Manifest.php#L613
We were seeing a 400 Bad Request response and not expected 200 OK even though webpack-dev-server was responding.
Changing the mix-manifest request from:
$client->request('GET', $path, [
RequestOptions::HEADERS => [
'User-Agent' => "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13\r\n",
'Accept' => '*/*',
],
]);
To:
$client->request('GET', $path, [
RequestOptions::HEADERS => [
'User-Agent' => "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13",
'Accept' => '*/*',
],
]);
Resulted with a 200 OK response.
We saw a following request while debugging this issue:
$ sudo tcpflow -c -i any host 172.18.0.2
172.018.000.003.48494-172.018.000.002.08080: GET /mix-manifest.json HTTP/1.1
Host: node:8080
User-Agent: User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13
Accept: */*
172.018.000.002.08080-172.018.000.003.48494: HTTP/1.1 400 Bad Request
Connection: close
Seems like the extra \r\n
is causing Guzzle to add an empty line before Accept
header turning the header into request's body.
craft-twigpack/src/helpers/Manifest.php
Line 287 in 53d8eb9
An exception is thrown when open_basedir is enabled when checking if a module URI is a filesystem path.
Instead of an exception, it could act as if is_file()
returns false.
I'm having issues getting favicons-webpack-plugin, html-webpack-plugin and craft-twigpack working together. I've followed along with your craft scaffolding, but can't quite get it working correctly.
The webapp.html
file is empty and no icons etc are injected into the head after running npm run build
...
Relevant configs from webpack.prod.js
:
// Configure Html webpack
const configureHtml = () => {
return {
templateContent: '',
filename: 'webapp.html',
inject: false,
};
};
// Configure Favicons webpack
const configureFavicons = () => {
return {
logo: settings.faviconConfig.logo,
prefix: settings.faviconConfig.prefix,
cache: false,
inject: true,
favicons: {
appName: pkg.name,
appDescription: pkg.description,
developerName: pkg.author.name,
developerURL: pkg.author.url,
theme_color: settings.faviconConfig.themeColor,
background: settings.faviconConfig.background,
appleStatusBarStyle: "black-translucent",
start_url: "/",
path: settings.paths.dist.base,
}
};
};
If I change inject
to true
for configureHtml
the webapp.html
is populated, but inside head
tags and includes the CSS and JS which is already being included elsewhere on the page. Any insight would be greatly appreciated.
The last sentence in the Configuring Twigpack section of the documentation reads:
For a slightly more simplified version of the above config,
But there is no end to this sentence. Does this simplified config exist anywhere?
A newer perhaps simpler approach to asynchronously loading css
https://www.filamentgroup.com/lab/load-css-simpler/
Is this something worth considering for twigpack?
I've got a site using Laravel Mix, and am coming from a misterbk/mix
plugin setup. Due to the site spanning various load-balanced servers, I need to have root-relative URLs, instead of absolute domain URLs. I've got it working just fine locally (using ddev under Windows), but I can't for the life of me get it to work on the remote server.
Relevant paths:
Manifest: @webroot/mix-manifest.json
CSS: @webroot/assets/css/all.css
JS: @webroot/assets/js/app.css
mix-manifest.json has:
{
"/assets/js/app.js": "/assets/js/app.js?id=b1341a8e6d5d440d33f67925d0e0d5d1",
"/assets/css/all.css": "/assets/css/all.css?id=a0089034478a1be737d8cf5ad8f6f704",
}
My layout template is referring to the above files like so:
<link rel="stylesheet" href="{{ craft.twigpack.getModuleUri('/assets/css/all.css') }}" title="All styles">
...
<script src="{{ craft.twigpack.getModuleUri('/assets/js/app.js') }}" defer></script>
Finally, my config/twigpack.php
in its entirety:
<?php
return [
// Global settings
'*' => [
// If `devMode` is on, use webpack-dev-server to all for HMR (hot module reloading)
'useDevServer' => false,
// Enforce Absolute URLs on includes
'useAbsoluteUrl' => false,
// The JavaScript entry from the manifest.json to inject on Twig error pages
// This can be a string or an array of strings
'errorEntry' => '',
// String to be appended to the cache key
'cacheKeySuffix' => '',
// Manifest file names
'manifest' => [
'legacy' => 'mix-manifest.json',
'modern' => 'mix-manifest.json',
],
// Public server config
'server' => [
'manifestPath' => '@webroot/',
'publicPath' => '/',
],
// webpack-dev-server config
'devServer' => [
'manifestPath' => '@webroot/',
'publicPath' => '/',
],
// Bundle to use with the webpack-dev-server
'devServerBuildType' => 'modern',
// Whether to include a Content Security Policy "nonce" for inline
// CSS or JavaScript. Valid values are 'header' or 'tag' for how the CSP
// should be included. c.f.:
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#Unsafe_inline_script
'cspNonce' => '',
// Local files config
'localFiles' => [
'basePath' => '@webroot/',
'criticalPrefix' => 'dist/criticalcss/',
'criticalSuffix' => '_critical.min.css',
],
],
// Development environment
'dev' => [
// If `devMode` is on, use webpack-dev-server to all for HMR (hot module reloading)
'useDevServer' => true,
],
// Staging (pre-production) environment
'staging' => [
],
// Live (production) environment
'production' => [
],
];
Now, when I load the site in that state, there's no output from the {{ craft.twigpack.getModuleUri() }}
tags, and the web.log
shows:
2022-07-28 14:22:10 [-][123042][-][error][nystudio107\twigpack\helpers\Manifest::reportError] Manifest file not found at: @webroot/assets/
Now, uhh, it's probably worth noting at this point that I used to have things set up in the recent past to use a mix-manifest.json
located at @webroot/assets/mix-manifest.json
(and in all honesty, I can go back to using it there if it makes any difference). However, as you can see, I have excised all references that I can find to that being the path, and yet somehow, Twigpack still thinks that mix-manifest is located under @webroot/assets/
. 🤨
And yes, I have cleared the Twigpack Manifest cache (as well as all the other ones that don't have to do with image transforms), to no avail.
Any pointers? 🆘 What am I missing?
Generating critical css for every element template is a bit overkill and they're frequently the same (especially if you're making heavy use of layouts). There should be a way to define fallback critical css files when twigpack isn't able to locate one dynamically.
A simple config setting for "criticalDefault" that would accept a file would suffice. Alternatively, the includeCriticalCssTags()
function could accept a fallback, akin to Twig's {% include() %}
tag.
The logic could be handled in Twig; however, it would be a lot of logic to have in a template. Alternatively, an event could be thrown to modify the criticalcss file to load; however, this feels a little overkill to me.
I'm struggling with one aspect of your excellent annotated webpack config, but think it might be more related to Twigpack.
sockjs-node/info
is being fetched from the server, rather than devServer, so each request is 404'ing. The relevant code is below, can you spot where I'm going wrong (or if you need more)?
twigpack.php
<?php
return [
// Global settings
'*' => [
// The JavaScript entry from the manifest.json to inject on Twig error pages
'errorEntry' => 'index.js',
// Manifest file names
'manifest' => [
'legacy' => 'manifest-legacy.json',
'modern' => 'manifest.json',
],
// Public server config
'server' => [
'manifestPath' => '@basePath/assets/',
'publicPath' => '',
],
// webpack-dev-server config
'devServer' => [
'manifestPath' => '@devServerBaseUrl/',
'publicPath' => '@devServerBaseUrl/',
],
// Local files config
'localFiles' => [
'basePath' => '@basePath/assets/',
'criticalPrefix' => 'criticalcss/',
'criticalSuffix' => '_critical.min.css',
],
],
// Local (development) environment
'dev' => [
// If `devMode` is on, use webpack-dev-server to all for HMR (hot module reloading)
'useDevServer' => true,
],
// Live (production) environment
'production' => [
'useDevServer' => false,
],
];
webpack.settings.js
...
devServerConfig: {
public: () => process.env.DEVSERVER_PUBLIC || 'http://localhost:5000',
host: () => process.env.DEVSERVER_HOST || 'localhost',
poll: () => process.env.DEVSERVER_POLL || false,
port: () => process.env.DEVSERVER_PORT || 5000,
https: () => process.env.DEVSERVER_HTTPS || false,
},
urls: {
live: process.env.URLS_LIVE,
local: process.env.URLS_LOCAL,
critical: process.env.URLS_LOCAL,
publicPath: () => process.env.PUBLIC_PATH || '/dist/public/',
},
...
webpack.dev.js
...
// Configure the webpack-dev-server
const configureDevServer = () => ({
public: settings.devServerConfig.public(),
contentBase: path.resolve(__dirname, 'dist/public'),
host: settings.devServerConfig.host(),
port: settings.devServerConfig.port(),
https: !!parseInt(settings.devServerConfig.https(), 10),
disableHostCheck: true,
quiet: true,
hot: true,
hotOnly: true,
overlay: true,
stats: 'errors-only',
watchOptions: {
poll: !!parseInt(settings.devServerConfig.poll(), 10),
ignored: /node_modules/,
},
headers: {
'Access-Control-Allow-Origin': '*',
},
...
So I am not sure if this is a bug, a limitation or I am doing something incorrectly.
So in the current project I am working on, within the craft CMS - all templates are set to _routers/pages
and then within this file I have the following:
_routers/pages.twig
{%- include [
'pages/' ~ entry.section.handle|replace({ 'Index': '' })|kebab ~ '/' ~ entry.type.handle|kebab,
'pages/' ~ entry.section.handle|replace({ 'Index': '' })|kebab ~ '/default.twig',
'pages/' ~ entry.section.handle|replace({ 'Index': '' })|kebab,
'pages/' ~ entry.type.handle|replace({ 'Index': '' })|kebab,
'pages/' ~ entry.type.handle|kebab,
'pages/_views/banner/default.twig',
] -%}
This in turn would load the following as examples:
pages/about.twig
, 'pages/terms/index.twig', 'pages/contact.twig' etc.
However, with this approach criticalCSS or rather the craft.twigpack.includeCriticalCssTags()
fails to load any files.
I have tried all sorts of combinations for paths and options.
To test this I have then moved out the about.twig
and contact.twig
files to the top level of the templates
directory and then within craft change the template from _routers/pages
to about
and contact
respectively. Upon doing this, the craft.twigpack.includeCriticalCssTags()
works perfectly.
This is also how I had setup my last project and it all worked fine.
But with this project and my intentions moving forward was to control either manually or dynamically (as above) all templates via a single router file. This means I can simply add the _routers/pages
to all sections, channels and singles and control the template output within the _routers/pages
file itself.
So, is there a way I can achieve this? Is it a bug? Should it perhaps look at {{ _self }}
to ensure the final template is a match to the critical paths? I am not sure how this translates, so this might be a completely bad idea.
Feel free to ping me on Discord if you want to chat this over?
Hi! I am using Twigpack with my Craft 3 installation.
Locally, everything works well, but when I deploy my project to my staging server on Laravel Forge, my assets are pulling the wrong path (they live within /web/dist/ and Twigpack is leaving out the /dist/ directory). I have updated my environment file, and tried different configurations with no luck. When I tried to spit out the URI to my CSS I get this Yii2 error:
Module does not exist in the manifest: main.css
The CSS version in the Twigpack path is correct with what is on the sever. Webpack is building fine.
I do need to get the Hash Value from a module for use cases like cookies or cache busting.
I created a pull request, not sure if it does make sense to you.
Thanks for the great work as always :)
The styles.js workaround as described here, is it now obsolete?
Because I get an error Undefined index: styles.js
when I leave this code in my layout.twig file:
<script nomodule>{{ craft.twigpack.includeFileFromManifest("styles.js") }}</script>
But that code was needed to make Javascript work on IE11.
I'm using the dev server mode and when trying to include a file from manifest:
{{ craft.twigpack.includeFileFromManifest("sprite.svg") }}
Twigpack appears to be appending the localFiles
basePath
causing the helper to try access
@webroot/http://localhost:8080/sprite.svg
Ideally I'd just run clear-caches/twigpack
on deploy.
I have a project setup, based on your Annotated Webpack config, that works perfectly in my Valet local environment setup. I cloned the project within a Nitro setup and everything works as expected—except for the webpack-dev-server/HMR. In my Twigpack config file, useDevServer is set to true as well as devMode in my general config. But Twigpack prints out the dist version of my JS and CSS (/dist/js/app.###.js
) rather than the devServer verion (http://localhost:8080/js/app.###.js
). Any idea what's going amiss with the Nitro setup?
Since the plugin grabs the siteUrl
and the language segments get attached to the path. Twigpack does not find the manifest files while on anything other than the primary site.
'siteUrl' => [
'en' => getenv('CRAFTENV_SITE_URL') . 'en/',
'de' => getenv('CRAFTENV_SITE_URL') . 'de/' ,
'fr' => getenv('CRAFTENV_SITE_URL') . 'fr/',
],
Not sure if this is a wrong config on my end, but I've tried updating all of the /web/
and @webroot
config paths that I have and can't seem to change this to be the actual path of /_compiled/
This is the path I am getting: /web/js/app.01223407b74d30b25aa7.js
It should be /_compiled/js/app.01223407b74d30b25aa7.js
This is my twigpack include:
{{ craft.twigpack.includeJsModule("app.js", true) }}
I use Twigpack in all Craft my projects in combination with Webpack, it's a great plugin!
Recently I found out that my ES6 scripts are not getting loaded by the browser, so I went digging.
I have found out that since the change in Twigpack was made, where you could define to include the script as async (in includeJsModule
), it will only load the legacy script.
Steps to reproduce the behaviour:
twigpack.php
define legacy and modern manifest files (default) and set useDevServer
to false
.{{ craft.twigpack.includeJsModule("site.js") }}
<script src="http://xyz.local/site-es5.js"></script>
The browser should load both modules: Modern and legacy
<script type="module" src="http://xyz.local/site-es2015.js"></script>
<script src="http://xyz.local/site-es5.js" nomodule></script>
Set async to true:
{{ craft.twigpack.includeJsModule("site.js", true) }}
I think this behavior should be fixed in code. In my opinion the async parameter is misleading for craft.twigpack.includeJsModule(...)
.
In the docs unter "Including JavaScript" you state:
You can also include a second optional parameter, to determine whether the JavaScript module should be loaded asynchronously or not (it defaults to false).
This does not mention, that in the case of false
, no modern script will be loaded.
On MDN they state:
There is no need to use the defer attribute (see <script> attributes) when loading a module script; modules are deferred automatically.
Source: Modules - Other_differences_between_modules_and_standard_scripts
Not sure if it's me being daft but it seems that the latest version of Twigpack assumes that you're running 'hot' from Webpack at all times when in local dev?
My experience before I ran the recent updates was that Twigpack would allow me to run using local files if webpack wasn't running (thus allowing for testing of builds). Now it seems I have to switch it on and off in the config to be able to test a fresh build.
Assume Twigpack was testing for the webpack devServer and falling back to localFiles on 404 which doesn't seem to be the case now.
I jumped from v1.1.8 to 1.1.10 in the latest update
Any ideas? Thank you.
Hey Andrew! Is it possible to make twigpack treat missing critical CSS templates as soft errors (similar to #2) instead of a hard 404 twig error when using the {{ craft.twigpack.includeCriticalCssTags() }}
tag?
i just tried to use your webpack-package locally with craft . i usually start craft with php server and mamp for mysql.
so if i start "yarn build" everything is working fine and compiled correctly. if i start "yarn dev" and "useDevServer" is true browser is loading and loading and no changes were applied. if i deactivate "useDevServer" my changes in css are not compiled directly (only if i execute "yarn build"). i dont know if my settings are correct?
thanks a lot and greetings from germany
return [
// Global settings
'*' => [
// If `devMode` is on, use webpack-dev-server to all for HMR (hot module reloading)
'useDevServer' => true,
// The JavaScript entry from the manifest.json to inject on Twig error pages
'errorEntry' => '',
// Manifest file names
'manifest' => [
'legacy' => 'manifest-legacy.json',
'modern' => 'manifest.json',
],
// Public server config
'server' => [
'manifestPath' => '@webroot/dist/',
'publicPath' => '/',
],
// webpack-dev-server config
'devServer' => [
'manifestPath' => 'http://localhost:8080/dist/',
'publicPath' => 'http://localhost:8080/',
],
// Local files config
'localFiles' => [
'basePath' => '@webroot/',
'criticalPrefix' => 'dist/criticalcss/',
'criticalSuffix' => '_critical.min.css',
],
],
// Live (production) environment
'live' => [
],
// Staging (pre-production) environment
'staging' => [
],
// Local (development) environment
'local' => [
// If `devMode` is on, use webpack-dev-server to all for HMR (hot module reloading)
'useDevServer' => true,
// The JavaScript entry from the manifest.json to inject on Twig error pages
'errorEntry' => 'app.js',
// webpack-dev-server config
'devServer' => [
'manifestPath' => 'http://localhost:8080/dist/',
'publicPath' => 'http://localhost:8080/',
],
],
];```
![Bildschirmfoto 2019-04-10 um 13 52 42](https://user-images.githubusercontent.com/11076634/55876445-f3346f80-5b97-11e9-8ec5-bb87186a99b5.png)
Support for ViteJS: https://vitejs.dev (looks like this is just handling their custom manifest file)
Currently have this working via a rollup mainfest plugin (https://github.com/shuizhongyueming/rollup-plugin-output-manifest) from within the ViteJS config but seems like a nice feature for TwigPack would be to allow non flat file mainfests.
Tried to use {{ craft.twigpack.includeCriticalCssTags("/path/to/foo.css") }}.
I did not get any error and inline CSS tags were not included.
This worked as replacement {{ craft.twigpack.includeInlineCssTags("@webroot/foo.css") }}
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.