pug-plugin
Advanced tools
Comparing version 2.1.0-alpha.0 to 2.1.0
# Change log | ||
## 2.1.0-beta.0 (2022-04-14) | ||
DON'T use this version!\ | ||
This is only for private temporary test. This version will be soon deleted. | ||
- feat: added supports the `responsive-loader` (EXPERIMENTAL) | ||
## 2.0.2 (2022-04-08) | ||
## 2.1.0 (2022-04-18) | ||
- feat: added supports the `responsive-loader` | ||
- feat: caching of an already processed asset when the same asset is required in different issuer files | ||
- fix: conflict of multiple styles with the same filename | ||
- fix: resolving url() in styles required in pug | ||
- fix: missing js file after rebuild by webpack serv | ||
- fix: potential collision when resolving resources for `compile` method | ||
@@ -14,0 +10,0 @@ - test: caching for styles required with same name |
{ | ||
"name": "pug-plugin", | ||
"version": "2.1.0-alpha.0", | ||
"version": "2.1.0", | ||
"description": "Pug plugin to extract html, css and js from pug templates defined in webpack entry.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -26,14 +26,3 @@ <div align="center"> | ||
Now is possible to use the source files of styles and scripts directly in pug. | ||
```pug | ||
link(href=require('./styles.scss') rel='stylesheet') | ||
script(src=require('./main.js')) | ||
``` | ||
The generated HTML contains hashed css and js filenames, depending on how webpack is configured. | ||
```html | ||
<link rel="stylesheet" href="/assets/css/styles.05e4dd86.css"> | ||
<script src="/assets/js/main.f4b855d8.js"></script> | ||
``` | ||
Now is possible to define only pug templates in webpack entry. All styles and scripts will be automatically extracted from pug. | ||
Now is possible to define pug templates in webpack entry. All styles and scripts will be automatically extracted from pug. | ||
```js | ||
@@ -52,2 +41,13 @@ const PugPlugin = require('pug-plugin'); | ||
Now is possible to use the source files of styles and scripts directly in pug. | ||
```pug | ||
link(href=require('./styles.scss') rel='stylesheet') | ||
script(src=require('./main.js')) | ||
``` | ||
The generated HTML contains hashed css and js filenames, depending on how webpack is configured. | ||
```html | ||
<link rel="stylesheet" href="/assets/css/styles.05e4dd86.css"> | ||
<script src="/assets/js/main.f4b855d8.js"></script> | ||
``` | ||
> 💡 The required styles and scripts in pug do not need to define in the webpack entry. | ||
@@ -59,9 +59,9 @@ > All required resources will be automatically handled by webpack. | ||
| Packages | Features | | ||
|-------------------------------------------------------------------------------------------|-----------------------------------------------------------------| | ||
| [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) | extract HTML from pug | | ||
| [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) | extract CSS from styles | | ||
| Packages | Features | | ||
|-------------------------------------------------------------------------------------------|---------------------------------------------------------------| | ||
| [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) | extract HTML from pug | | ||
| [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) | extract CSS from styles | | ||
| [webpack-remove-empty-scripts](https://github.com/webdiscus/webpack-remove-empty-scripts) | prevent generating empty files by the `mini-css-extract-plugin` | | ||
| [resolve-url-loader](https://github.com/bholloway/resolve-url-loader) | resolve the url in CSS | | ||
| [pug-loader](https://github.com/webdiscus/pug-loader) | the pug loader is already included in the pug plugin | | ||
| [resolve-url-loader](https://github.com/bholloway/resolve-url-loader) | resolve the url in CSS | | ||
| [pug-loader](https://github.com/webdiscus/pug-loader) | the pug loader is already included in the pug plugin | | ||
@@ -595,4 +595,4 @@ You can replace all of the above packages with just one pug plugin. | ||
> ### ✅ Correct ways | ||
> 1. Add a source style file directly in pug via `require`> | ||
> ### ✅ Correct way | ||
> Add a source style file directly in pug via `require`: | ||
> ```pug | ||
@@ -603,10 +603,2 @@ > html | ||
> ``` | ||
> **This is the correct standard way, strongly recommended.** | ||
> | ||
> 2. Add a compiled css file directly in pug and add the source file in webpack entry: | ||
> ```pug | ||
> html | ||
> head | ||
> link(rel='stylesheet' href='/assets/css/styles.css') | ||
> ``` | ||
@@ -613,0 +605,0 @@ ### Extract HTML from file defined in webpack entry |
134
src/index.js
@@ -145,12 +145,9 @@ const vm = require('vm'); | ||
EntryPlugin: null, | ||
AssetScript: null, | ||
/** | ||
* @param {Compilation} compilation The instance of the webpack compilation. | ||
* @param {AssetScript} AssetScript The instance of the AssetScript. | ||
*/ | ||
init(compilation, AssetScript) { | ||
init(compilation) { | ||
this.compilation = compilation; | ||
this.EntryPlugin = compilation.compiler.webpack.EntryPlugin; | ||
this.AssetScript = AssetScript; | ||
this.resetAdditionalEntries(); | ||
@@ -194,2 +191,3 @@ }, | ||
* | ||
* @param {string} name | ||
* @param {string} importFile | ||
@@ -202,4 +200,3 @@ * @param {string} filenameTemplate | ||
*/ | ||
addToCompilation({ importFile, filenameTemplate, outputPath, context, issuer }) { | ||
let name = this.AssetScript.getUniqueName(importFile, issuer); | ||
addToCompilation({ name, importFile, filenameTemplate, outputPath, context, issuer }) { | ||
// ignore duplicate entries with same name | ||
@@ -303,8 +300,7 @@ if (name === false) return false; | ||
const RawSource = compilation.compiler.webpack.sources.RawSource; | ||
let existsScripts = []; | ||
// in the content, replace the source script file with the output filename | ||
for (let asset of this.files) { | ||
let { request: sourceFile, filename: assetFile, chunkFiles } = asset; | ||
const issuerFile = asset.issuer.filename; | ||
let { request: sourceFile, chunkFiles } = asset; | ||
@@ -315,46 +311,34 @@ if (!compilation.assets.hasOwnProperty(issuerFile)) { | ||
} | ||
let chunkScripts = ''; | ||
let newContent; | ||
const content = compilation.assets[issuerFile].source(); | ||
const chunk = compilation.namedChunks.get(asset.name); | ||
let chunkScripts = '', | ||
chunkFile, | ||
newContent; | ||
chunkFiles = chunk.files; | ||
asset.chunkFiles = chunkFiles; | ||
// save asset filenames to cache for webpack serve, watch | ||
if (assetFile == null) { | ||
const chunkGroup = compilation.namedChunkGroups.get(asset.name); | ||
const entrypointChunk = chunkGroup.getEntrypointChunk(); | ||
chunkFile = entrypointChunk.files.values().next().value; | ||
assetFile = path.posix.join(outputPublicPath, chunkFile); | ||
chunkFiles = chunkGroup.getFiles(); | ||
asset.filename = assetFile; | ||
asset.chunkFiles = chunkFiles; | ||
} | ||
// replace source filename with asset filename | ||
if (chunkFiles.length > 1) { | ||
existsScripts.push(chunkFile); | ||
if (chunkFiles.size === 1) { | ||
const assetFile = path.posix.join(outputPublicPath, chunkFiles.values().next().value); | ||
newContent = content.replace(sourceFile, assetFile); | ||
} else { | ||
// generate additional scripts of chunks | ||
for (let file of chunkFiles) { | ||
if (existsScripts.indexOf(file) < 0) { | ||
const scriptFile = path.posix.join(outputPublicPath, file); | ||
chunkScripts += `<script src="${scriptFile}"></script>`; | ||
existsScripts.push(file); | ||
} | ||
const assetsInfo = compilation.assetsInfo.get(file); | ||
if (assetsInfo.hotModuleReplacement === true) continue; | ||
const scriptFile = path.posix.join(outputPublicPath, file); | ||
chunkScripts += `<script src="${scriptFile}"></script>`; | ||
} | ||
// inject generated chunks before original <script> and replace source file with output filename | ||
const srcStartPos = content.indexOf(sourceFile); | ||
const srcEndPos = srcStartPos + sourceFile.length; | ||
let tagStartPos = srcStartPos; | ||
while (tagStartPos >= 0 && content.charAt(--tagStartPos) !== '<') {} | ||
newContent = | ||
content.slice(0, tagStartPos) + | ||
chunkScripts + | ||
content.slice(tagStartPos, srcStartPos) + | ||
assetFile + | ||
content.slice(srcEndPos); | ||
} else { | ||
newContent = content.replace(sourceFile, assetFile); | ||
// inject generated chunks <script> and replace source file with output filename | ||
if (chunkScripts) { | ||
const srcPos = content.indexOf(sourceFile); | ||
let tagStartPos = srcPos; | ||
let tagEndPos = srcPos + sourceFile.length; | ||
while (tagStartPos >= 0 && content.charAt(--tagStartPos) !== '<') {} | ||
tagEndPos = content.indexOf('</script>', tagEndPos) + 9; | ||
newContent = content.slice(0, tagStartPos) + chunkScripts + content.slice(tagEndPos); | ||
} | ||
} | ||
@@ -364,4 +348,2 @@ | ||
} | ||
// --> console.log('\n -+-+-+ replaceSourceFilesInCompilation:\n', this.files, existsScripts); | ||
}, | ||
@@ -401,4 +383,10 @@ | ||
add(name, request, issuer) { | ||
// prevent to add duplicates by webpack serve, watch | ||
if (this.files.find((item) => item.request === request && item.issuer.request === issuer)) return; | ||
let cachedFile = this.files.find((item) => item.request === request && item.issuer.request === issuer); | ||
if (cachedFile) { | ||
// update the name for the script | ||
// after rebuild by hmr the same request can be generated with other asset name | ||
cachedFile.name = name; | ||
cachedFile.chunkFiles = new Set(); | ||
return; | ||
} | ||
@@ -408,4 +396,3 @@ this.files.push({ | ||
request, | ||
filename: undefined, | ||
chunkFiles: [], | ||
chunkFiles: new Set(), | ||
issuer: { | ||
@@ -619,3 +606,3 @@ filename: undefined, | ||
urlDependencyResolver.init(normalModuleFactory.fs.fileSystem, compiler.options); | ||
AssetEntry.init(compilation, AssetScript); | ||
AssetEntry.init(compilation); | ||
AssetTrash.reset(); | ||
@@ -632,3 +619,5 @@ AssetScript.reset(); | ||
const { issuer } = resolveData.contextInfo; | ||
let name = AssetScript.getUniqueName(importFile, issuer); | ||
const res = AssetEntry.addToCompilation({ | ||
name, | ||
importFile, | ||
@@ -824,5 +813,3 @@ filenameTemplate: webpackScriptFilename, | ||
//resourceResolver.addToChunkCache(module, assetFile); | ||
resourceResolver.addToChunkCache(module, path.posix.join(webpackPublicPath, assetFile)); | ||
//resourceResolver.addToChunkCache2(context, module.rawRequest, assetFile); | ||
resourceIssuer = sourceFile; | ||
@@ -833,29 +820,9 @@ } else if (module.type === 'asset/resource') { | ||
// TODO: refactoring code | ||
// TODO: refactoring code for 'responsive-loader' | ||
// -- BEGIN resource loader -- | ||
const resourceQuery = url.parse(module.rawRequest, true).query; | ||
// console.log( | ||
// '\n +++ addToChunkCache2: ', | ||
// assetFile, | ||
// module.type, | ||
// module.isDependencyTypeUrl, | ||
// '\n', | ||
// context, | ||
// '\n- rawRequest: ', | ||
// module.rawRequest, | ||
// '\n- assetFile: ', | ||
// assetFile, | ||
// //'\n- assets: ', | ||
// //buildInfo.assets, | ||
// //'\n- assetsInfo: ', | ||
// // buildInfo.assetsInfo, | ||
// '\n- resourceQuery: ', | ||
// resourceQuery | ||
// ); | ||
if (resourceQuery && resourceQuery.prop) { | ||
const prop = resourceQuery.prop; | ||
const source = module?.originalSource()?.source()?.toString(); | ||
//console.log(' ~~~~ COMPILED source: ', source); | ||
@@ -872,5 +839,2 @@ if (source) { | ||
assetFile = result[prop]; | ||
//console.log('\n~~~~ COMPILED ASSET: ', resourceQuery); | ||
resourceResolver.addToChunkCache(module, assetFile); | ||
@@ -904,4 +868,2 @@ | ||
assetFile = realAssetFile; | ||
// TODO: add original assetFile to trash | ||
//console.log('\n xxx DELETE original assetFile: ', buildInfo.filename, ' => OK: ', assetFile); | ||
resourceResolver.addToChunkCache(module, assetFile); | ||
@@ -918,14 +880,5 @@ | ||
continue; | ||
// assetFile = { | ||
// src: 'img/favicon.2ff47510-300w.webp', | ||
// srcSet: 'img/favicon.2ff47510-300w.webp 300w', | ||
// }; | ||
} | ||
} | ||
} | ||
// if (assetFile !== buildInfo.filename) { | ||
// console.log('\n === REAL assetFile: ', buildInfo.filename, ' => ', assetFile); | ||
// } | ||
// -- END resource loader -- | ||
@@ -947,6 +900,3 @@ | ||
} else { | ||
//console.log('\n +++ addToChunkCache:\n', context, '\n', '\n- ', module.rawRequest, '\n- ', assetFile); | ||
resourceResolver.addToChunkCache(module, assetFile); | ||
//resourceResolver.addToChunkCache2(context, module.rawRequest, assetFile); | ||
} | ||
@@ -1040,4 +990,2 @@ } | ||
//if (assetFile === 'index.html') console.log('### compiledCode: ', assetFile, sourceCjs, '\n\n:', compiledCode); | ||
try { | ||
@@ -1044,0 +992,0 @@ result = isFunction(compiledCode) ? compiledCode() : compiledCode; |
@@ -235,20 +235,2 @@ const path = require('path'); | ||
/** | ||
* Add the context and resolved path of the resource to resolve it in require() at render time. | ||
* | ||
* @param {string} context The context directory of required resource. | ||
* @param {string} request The raw request. | ||
* @param {string} assetFile The web path of the asset. | ||
*/ | ||
addToChunkCache2(context, request, assetFile) { | ||
// Note: when the same resource module is used multiple times, | ||
// only the first module is stored in the chunk, | ||
// so using the issuer of the resource module is not reliable. | ||
// The true issuer is the last used parent module of this resource module. | ||
const assetId = this.getId(context, request); | ||
this.chunkCache.files.set(assetId, assetFile); | ||
this.chunkCache.paths.add(context); | ||
}, | ||
/** | ||
* @param {string} resource The full path of source resource. | ||
@@ -329,16 +311,2 @@ * @param {string} rawRequest The raw request of resource is argument of URL() in css. | ||
// console.log( | ||
// '\n ====> RESOLVE:', | ||
// file, | ||
// '\n - issuer: ', | ||
// issuer, | ||
// '\n - context: ', | ||
// context, | ||
// '\n', | ||
// this.chunkCache.files, | ||
// this.chunkCache.paths, | ||
// this.moduleCache, | ||
// this.globalCache.paths | ||
// ); | ||
// try to resolve a resource required in pug by absolute path of source file | ||
@@ -402,21 +370,2 @@ if (path.isAbsolute(file)) { | ||
if (assetFile) { | ||
if (assetFile === 'img/1033740.9f92ec83-320w.webp') { | ||
console.log('\n --- RESOLVED assetFile: ', assetFile); | ||
// return { | ||
// src: 'img/favicon.2ff47510-300w.webp', | ||
// srcSet: 'img/favicon.2ff47510-300w.webp 300w', | ||
// }; | ||
} | ||
// if (typeof assetFile !== 'string') { | ||
// console.log('\n --- RESOLVED assetFile: ', this.issuer, assetFile); | ||
// //return "module.exports = { src: '### SRC ###', srcSet: '### srcSet ###' };"; | ||
// return { | ||
// src: 'img/favicon.2ff47510-300w.webp', | ||
// srcSet: 'img/favicon.2ff47510-300w.webp 300w', | ||
// }; | ||
// } | ||
//return typeof assetFile === 'string' ? path.posix.join(self.publicPath, assetFile) : assetFile; | ||
return assetFile; | ||
@@ -423,0 +372,0 @@ } |
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
0
0
95681
1582
928