Giter Site home page Giter Site logo

nystudio107 / craft-twigpack Goto Github PK

View Code? Open in Web Editor NEW
97.0 6.0 22.0 1.01 MB

Twigpack is a bridge between Twig and webpack, with manifest.json & webpack-dev-server HMR support

Home Page: https://nystudio107.com/

License: MIT License

PHP 100.00%
craftcms craft-plugin twig webpack webpack-dev-server hmr-support manifest-json asset revision mix

craft-twigpack's Introduction

Scrutinizer Code Quality Code Coverage Build Status Code Intelligence Status

Twigpack plugin for Craft CMS 5.x

Twigpack is a bridge between Twig and webpack, with manifest.json & webpack-dev-server HMR support

Screenshot

Related Article: An Annotated webpack 4 Config for Frontend Web Development

Requirements

This plugin requires Craft CMS 5.0.0 or later.

Installation

To install the plugin, follow these instructions.

  1. Open your terminal and go to your Craft project:

     cd /path/to/project
    
  2. Then tell Composer to load the plugin:

     composer require nystudio107/craft-twigpack
    
  3. Install the plugin via ./craft install/plugin twigpack via the CLI, or in the Control Panel, go to Settings → Plugins and click the “Install” button for Twigpack.

You can also install Twigpack via the Plugin Store in the Craft Control Panel.

Documentation

Click here -> Twigpack Documentation

Twigpack Roadmap

Some things to do, and ideas for potential features:

  • Release it

Brought to you by nystudio107

craft-twigpack's People

Contributors

augustmiller avatar bighoho123 avatar chasegiunta avatar chrisrowe avatar dubcanada avatar gbowne-quickbase avatar hendrikeng avatar kashkin avatar khalwat avatar paweltatarczuk avatar timkelty avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

craft-twigpack's Issues

Run Twigpack mit webpack-package locally

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)

webpack-dev-server/HMR not working in Nitro setup

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?

Does update 1.2.4 removes the need for the styles.js workaround?

Question

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.

Ability to get the Hash Value of a module

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 :)

#27

getModuleUri giving the correct URL to CSS but includeCssModule doesn't include the CSS on the page

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!

CSS cache not breaking

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?

Hard error on missing critical templates

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?

Dumping config

When I install this plugin I get an unknown error and the config is dumped in the page:
image

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

Multisite 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/',
],

Request to mix-manifest.json is malformed

Describe the bug

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.

To reproduce

Steps to reproduce the behaviour:

  1. Set up a craft-twigpack with webpack-dev-server (HMR enabled)
  2. Try visiting a Craft's page
  3. Webpack responds with 400 Bad request

This should be easily seen with a tcpflow:

$ sudo tcpflow -c -i any host localhost and port 8080

Expected behaviour

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: */*

Investigation

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.

Versions

  • Plugin version: 1.2.12
  • Craft version: 3.5.19.1

isHot not set properly before use

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.

#29

sockjs-node/info not fetched from dev server

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': '*',
  },
...

Twigpack outputs empty strings on Docker

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?

"modern" script not loaded when async is missing

Describe the bug

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.

To reproduce

Steps to reproduce the behaviour:

  1. In twigpack.php define legacy and modern manifest files (default) and set useDevServer to false.
  2. In a twig template include the JS module like so:
{{ craft.twigpack.includeJsModule("site.js") }}
  1. Load the website
  2. The browser will only load the legacy module script.
<script src="http://xyz.local/site-es5.js"></script>

Expected behaviour

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>

Fix

Set async to true:

{{ craft.twigpack.includeJsModule("site.js", true) }}

Versions

  • Plugin version: 1.2.7
  • Craft version: 3.5.17.1

Additional notes

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

includeCriticalCssTags() returns empty

{{ 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.

includeCriticalCssTags not working when setting own path

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") }}

Aliases like @webroot not working

Describe the bug

In the docs there is a use case of the alias @webroot

'server' => [
    'manifestPath' => '@webroot/',
    'publicPath' => '/',
],

To reproduce

Steps to reproduce the behaviour:

  1. Set the manifestPath to '@webroot'
  2. Make sure you've setup the alias in the config/general.php
  3. Run a production build with NPM and make sure you set your .ENV (ENVIRONMENT=production)
  4. Use {{ craft.twigpack.getModuleUri("main.js") }} in you twig template
  5. Error message: Cat:nystudio107\twigpack\helpers\Manifest::reportError Message: Manifest file not found at: @webroot

Expected behaviour

@webroot alias should be converted so the path is correct ( Craft::getAlias('@webroot') )

Versions

  • Plugin version: 1.2.13
  • Craft version: 3.6.12

new dev mode behaviour?

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.

Cannot load criticalcss if router file is used instead of a the specific template path in the CMS

Question

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?

Twigpack

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.

support chunks-webpack-plugin

Is your feature request related to a problem? Please describe.

support the inclusion of the related chunks created with webpack chunks: 'all'

Describe the solution you would like

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"
]
}
}

Describe alternatives you have considered

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.

Additional context

adding new function for backwards compat.

[FR] CSP nonce support

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.

includeJsModule being quirky

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..

Issues with twigpack cache on Heroku

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.

Allow getFileFromManifest to load files from webpack-dev-server

I've taken at how how I think this function should work, but I have two main concerns:

  1. It works for my setup, where if I've run a build, this will return built and cache-broken local files. And, if I'm running webpack-dev-server, that script will first clean my built files so that the logic of this function works.
  2. I don't think the config variables I'm using are the best choice, but again, they work for me.
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 '';
}

Let me define a fallback CSS file for criticalcss

Is your feature request related to a problem? Please describe.

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.

Describe the solution you would like

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.

Describe alternatives you have considered

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.

Missing css files when using dev-server

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?

Issues with craft.twigpack.includeFileFromManifest and webapp.html

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.

Question about Prefetch/Preload

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.

Hashes wrong (cache?) in production - ideas why?

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.

4.0.0 release

Hi,

Wondering if a stable release for Craft 4 is planned to be released soon ?
Thanks

Multisite issues with manifest file

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?

Twigpack is stuck on where it thinks mix-manifest is located

Question

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?

includeFileFromManifest() misforming path

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

`craft.twigpack.includeFileFromManifest` isn't inserting anything

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

404 on files - wrong bundle path

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) }}

Rendering templates with multiple getModuleUri calls is extremely slow after release v1.2.12

Describe the bug

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).

To reproduce

  1. In config twigpack.php, set 'useDevServer' => true and enable devMode in craft config.
  2. Ensure webpack-dev-server is not running.
  3. In a twig template, call craft.twigpack.getModuleUri multiple times (i'm loading optimized versioned svg and images from the manifest file in this way)

Expected behaviour

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.

Versions

  • Plugin version: >= 1.2.12
  • Craft version: 3

Easy way to test production bundle.

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.

FR: Support for self-signed certificates in devMode

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?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.