New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

laravel-mix-versionhash

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

laravel-mix-versionhash - npm Package Compare versions

Comparing version 1.0.8 to 1.1.0

2

package.json
{
"license": "MIT",
"version": "1.0.8",
"version": "1.1.0",
"author": "ctf0",

@@ -5,0 +5,0 @@ "name": "laravel-mix-versionhash",

@@ -31,4 +31,1 @@ <h1 align="center">

| delimiter | string | `'.'` | the delimiter for filename and hash, <br> note that anything other than `. - _` will be removed |
## TODO
- add option to exclude files from hashing.
const mix = require('laravel-mix')
const File = require('laravel-mix/src/File')
const proxyMethod = require('proxy-method')
const ConcatenateFilesTask = require('laravel-mix/src/tasks/ConcatenateFilesTask')
const forIn = require('lodash/forIn')
const jsonfile = require('jsonfile')
const escapeStringRegexp = require('escape-string-regexp')

@@ -9,41 +11,52 @@ const ExtractTextPlugin = require('extract-text-webpack-plugin')

/**
* Version Hash for Laravel Mix.
*
* @see https://laravel-mix.com/
*/
class VersionHash {
register(options = {}) {
this.options = Object.assign(
{
length: 6,
delimiter: separator,
exclude: []
},
options
)
const delimiter = escapeStringRegexp(this.getDelimiter())
const mixManifest = `${Config.publicPath}/${Mix.manifest.name}`
const removeHashFromKeyRegex = new RegExp(`${delimiter}([a-f0-9]{${this.options.length}})\\.([^.]+)$`, 'g')
const removeHashFromKeyRegexWithMap = new RegExp(`${delimiter}([a-f0-9]{${this.options.length}})\\.([^.]+)\\.map$`, 'g')
/**
* Constructor.
*/
constructor() {
// hash the generated assets once build is complete
this.registerHashAssets()
return mix.webpackConfig().then(() => {
jsonfile.readFile(mixManifest, (err, obj) => {
let newJson = {}
forIn(obj, (value, key) => {
key = key.endsWith('.map')
? key.replace(removeHashFromKeyRegexWithMap, '.$2.map')
: key.replace(removeHashFromKeyRegex, '.$2')
newJson[key] = value
})
jsonfile.writeFile(mixManifest, newJson, {spaces: 2}, (err) => {
if (err) console.error(err)
})
})
})
// look for instances of combining file(s)
this.hashForCombine()
}
/**
* Dependencies for plugin.
*
* @return {String[]}
*/
dependencies() {
return ['jsonfile', 'escape-string-regexp', 'path']
return [
'jsonfile',
'escape-string-regexp',
'path',
'proxy-method
]
}
/**
* Plugin functionality.
*
* @param {{length: {Number}, delimiter: {String}, exclude: {String[]}}} options
*/
register(options = {}) {
this.options = Object.assign({
length: 6,
delimiter: separator,
exclude: []
}, options)
}
/**
* Apply configuration to webpack configuration.
*
* @param {Object} webpackConfig
*/
webpackConfig(webpackConfig) {

@@ -55,10 +68,11 @@ const length = this.options.length

let chunkhash = `[name]${delimiter}[chunkhash:${length}].js`
let usesExtract = webpackConfig.optimization && webpackConfig.optimization.runtimeChunk
webpackConfig.output.filename = chunkhash
let usesExtract = webpackConfig.optimization && webpackConfig.optimization.runtimeChunk
if (webpackConfig.output.chunkFilename && !usesExtract) {
// merge chunkFilename paths
let directory = path.dirname(webpackConfig.output.chunkFilename)
webpackConfig.output.chunkFilename = `${directory}/${chunkhash}`
} else {

@@ -71,3 +85,4 @@ webpackConfig.output.chunkFilename = chunkhash

forIn(webpackConfig.plugins, (value, key) => {
forIn(webpackConfig.plugins, value => {
if (value instanceof ExtractTextPlugin && !value.filename.includes(contenthash)) {

@@ -81,15 +96,104 @@

}
}
})
}
/**
* Update backslashes to forward slashes for consistency.
*
* @return {Object}
*/
webpackPlugins() {
const combinedFiles = this.combinedFiles
return new class {
apply(compiler) {
compiler.plugin('done', stats => {
forIn(stats.compilation.assets, (asset, path) => {
if (combinedFiles[path]) {
delete stats.compilation.assets[path]
stats.compilation.assets[path.replace(/\\/g, '/')] = asset
}
})
})
}
}
}
/**
* Get configured delimiter with appropriate filtering.
*
* @return {String}
*/
getDelimiter() {
return this.options.delimiter.replace(/[^\.|\-|_]/g, '') || separator
return this.options.delimiter.replace(/[^.\-_]/g, '') || separator
}
/**
* TODO vet whether or not this needs to exist...?
*/
exclude(key) {
return this.options.exclude.some((e) => e == key)
return this.options.exclude.some(e => e == key)
}
/**
* Add listener to account for hashing in filename(s) persisted to manifest.
*
* @return {this}
*/
registerHashAssets() {
Mix.listen('build', () => {
let op_length = this.options.length
const delimiter = escapeStringRegexp(this.getDelimiter())
const removeHashFromKeyRegex = new RegExp(`${delimiter}([a-f0-9]{${op_length}})\\.([^.]+)$`, 'g')
const removeHashFromKeyRegexWithMap = new RegExp(`${delimiter}([a-f0-9]{${op_length}})\\.([^.]+)\\.map$`, 'g')
const file = File.find(`${Config.publicPath}/${Mix.manifest.name}`)
let newJson = {}
forIn(JSON.parse(file.read()), (value, key) => {
if (key.endsWith('.map')) {
key = key.replace(removeHashFromKeyRegexWithMap, '.$2.map')
} else {
key = key.replace(removeHashFromKeyRegex, '.$2')
}
newJson[key] = value
})
file.write(newJson)
})
return this
}
/**
* Intercept functionality that generates combined asset(s).
*
* @return {this}
*/
hashForCombine() {
this.combinedFiles = {}
// hook into Mix's task collection to update file name hashes
proxyMethod.before(Mix, 'addTask', task => {
if (task instanceof ConcatenateFilesTask) {
proxyMethod.after(task, 'merge', () => {
const file = task.assets.pop()
const hash = `${this.getDelimiter()}${file.version().substr(0, this.options.length)}`
const hashed = file.rename(`${file.nameWithoutExtension()}${hash}${file.extension()}`)
task.assets.push(hashed)
this.combinedFiles[hashed.pathFromPublic()] = true
})
}
})
return this
}
}
mix.extend('versionHash', new VersionHash())
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc