在 Webpack 插件中插入一个函数
Inserting a function in Webpack Plugin
有谁知道如何在 Webpack 插件中插入和重用函数?就像从我的插件中插入该函数 myFunction()
并从生成的包中调用它?
背景资料:
我正在替换其他库中某些资产的一些路径。
- 图书馆 A 使用 file1.afm 到 file14.afm
- 图书馆 B 使用 file1.trie 到 file4.trie
我使用 file-loader
将这些文件放入我的包中,然后我需要每个文件:
const f1 = require('file1.afm')
每个文件依此类推。
但是图书馆 A 和 B 正在做类似以下的事情:
data = base64.toByteArray(fs.readFileSync('../src/js/somePath/inLibrary/Private/file1.afm', 'base64'));
对于每个文件。我想用正确的包路径替换该路径,但 __dirname
没有帮助。这就是为什么我想使用 callsites.
我想做的是将 callsites 作为全局依赖项插入到我的包中,并像 __webpack_require__(moduleId)
一样使用它,这样我就可以拉入正在执行的 js 文件路径(__dirname
或 __filename
不起作用)
所以理论上我会插入 callsites()[0].getFileName() + __webpack_require__(moduleId)
到目前为止我的配置是这样的,webpack-file-resolver
是我正在做的当前插件:
const path = require('path')
const webpackTs = require('webpack-config-typescript')
var WebpackFileResolver = require('webpack-file-resolver')
let config = {
entry: path.join(__dirname, 'src/handler.ts'),
target: 'node',
output: {
filename: 'deploy/handler_[hash].js',
libraryTarget: 'commonjs',
path: path.join(__dirname)
}
}
config = webpackTs.ts(config)
config.module.rules.push({
test: /\.(ttf|trie|afm)$/,
loader: "file-loader",
options: {
name: "[name].[ext]",
outputPath: "deploy",
publicPath: "./"
},
})
config.plugins.push(new WebpackFileResolver({
test: /\.(trie|afm)$/,
serverPath: "./"
}))
module.exports = config
到目前为止,这是我得到的:
const ConcatSource = require("webpack-sources").ConcatSource
function getRequires (options, chunks) {
return chunks.reduce((c, chunk) => {
chunk.forEachModule((module) => {
const deps = module && module.fileDependencies && module.fileDependencies || []
deps.forEach((filepath) => {
if(options.test.test(filepath)) {
c.add({
path: filepath,
id: module.id
})
}
})
})
return c
}, new Set())
}
class WebpackFileResolverPlugin {
constructor(options = {}) {
this.options = options
}
apply(compiler) {
const options = this.options
compiler.plugin('compilation', (compilation) => {
compilation.plugin('optimize-chunk-assets', (chunks, done) => {
const requires = getRequires(options, chunks)
replaceBundleReadDir(compilation, chunks, requires)
done()
})
})
}
}
function replaceBundleReadDir(compilation, chunks, requires){
chunks.forEach(function (chunk) {
chunk.files.forEach(function (fileName) {
replaceSource(compilation, fileName, requires)
})
})
}
function replaceSource(compilation, fileName, requires){
let result = compilation.assets[fileName].source()
const source = []
requires.forEach((require) => {
let buffer = []
for (let c of result) {
if (c !== '\n') {
buffer.push(c)
} else {
const line = buffer.join('')
const newLine = replaceFsReadDir (require, line)
if (newLine !== undefined) {
result = result.replace(line, newLine)
}
buffer = []
}
}
})
compilation.assets[fileName] = new ConcatSource(result)
}
function replaceFsReadDir (require, line) {
const webpackRequire = '__webpack_require__'
const fileName = require.path.replace(/^.*[\\/]/, '')
const fileStartMarker = line.indexOf(fileName)
const readDirMarker = line.lastIndexOf('readFile')
if (fileStartMarker !== -1 && readDirMarker !== -1) {
let fileEndMarker = line.indexOf(')', fileStartMarker)
let getEnd = line.slice(fileStartMarker, fileEndMarker + 1)
fileEndMarker = (getEnd.length > fileName.length + 2) ? line.indexOf(',', fileStartMarker) : fileEndMarker
const startSlice = line.indexOf('(', readDirMarker) + 1
const newLine = `${line.slice(0, startSlice)}${webpackRequire}(${require.id})${line.slice(fileEndMarker)}`
return newLine
} else {
return undefined
}
}
module.exports = WebpackFileResolverPlugin
同时我将使用以下内容,它非常老套,所以我不能真正推荐它。
我所做的是将我的全局函数添加到我的包中,然后将路径替换为当前正在执行的路径 javascript。如有任何想法,我们将不胜感激。
const ConcatSource = require("webpack-sources").ConcatSource
// This is the function I want to use on my bundle
const noRestForTheWicked = `
const __callsites__ = () => {
const _ = Error.prepareStackTrace;
Error.prepareStackTrace = (_, stack) => stack;
const stack = new Error().stack.slice(1);
Error.prepareStackTrace = _;
return stack;
}
const __current_file__ = () => {
const sep = require('path').sep
let filePieces = __callsites__()[0].getFileName().split(sep)
return filePieces.slice(0, -1).join(sep) + sep
};
`
function getRequires (options, chunks) {
return chunks.reduce((c, chunk) => {
chunk.forEachModule((module) => {
const deps = module && module.fileDependencies && module.fileDependencies || []
deps.forEach((filepath) => {
if(options.test.test(filepath)) {
c.add({
path: filepath,
id: module.id
})
}
})
})
return c
}, new Set())
}
class WebpackFileResolverPlugin {
constructor(options = {}) {
this.options = options
}
apply(compiler) {
const options = this.options
compiler.plugin('compilation', (compilation) => {
compilation.plugin('optimize-chunk-assets', (chunks, done) => {
const requires = getRequires(options, chunks)
replaceBundleReadDir(compilation, chunks, requires, options)
done()
})
})
}
}
function replaceBundleReadDir(compilation, chunks, requires, options){
chunks.forEach(function (chunk) {
chunk.files.forEach(function (fileName) {
replaceSource(compilation, fileName, requires, options)
})
})
}
function replaceSource(compilation, fileName, requires, options){
let result = compilation.assets[fileName].source()
if ('serverPath' in options && options.serverPath !== undefined) {
// This is where the hacking happens
result = noRestForTheWicked + result
}
requires.forEach((require) => {
let buffer = []
for (let c of result) {
if (c !== '\n') {
buffer.push(c)
} else {
const line = buffer.join('')
const newLine = replaceFsReadDir (require, line, options)
if (newLine !== undefined) {
result = result.replace(line, newLine)
}
buffer = []
}
}
})
compilation.assets[fileName] = new ConcatSource(result)
}
function replaceFsReadDir (require, line, options) {
const webpackRequire = '__webpack_require__'
const fileName = require.path.replace(/^.*[\\/]/, '')
const fileStartMarker = line.indexOf(fileName)
const readDirMarker = line.lastIndexOf('readFile')
if (fileStartMarker !== -1 && readDirMarker !== -1) {
let fileEndMarker = line.indexOf(')', fileStartMarker)
let getEnd = line.slice(fileStartMarker, fileEndMarker + 1)
fileEndMarker = (getEnd.length > fileName.length + 2) ? line.indexOf(',', fileStartMarker) : fileEndMarker
const startSlice = line.indexOf('(', readDirMarker) + 1
let importStr = `${webpackRequire}(${require.id})`
if ('serverPath' in options && options.serverPath !== undefined) {
// Server Land, brace for impact, inserting the thing
importStr = `__current_file__() + ${importStr}`
}
const newLine = `${line.slice(0, startSlice)}${importStr}${line.slice(fileEndMarker)}`
return newLine
} else {
return undefined
}
}
module.exports = WebpackFileResolverPlugin
有谁知道如何在 Webpack 插件中插入和重用函数?就像从我的插件中插入该函数 myFunction()
并从生成的包中调用它?
背景资料:
我正在替换其他库中某些资产的一些路径。
- 图书馆 A 使用 file1.afm 到 file14.afm
- 图书馆 B 使用 file1.trie 到 file4.trie
我使用 file-loader
将这些文件放入我的包中,然后我需要每个文件:
const f1 = require('file1.afm')
每个文件依此类推。
但是图书馆 A 和 B 正在做类似以下的事情:
data = base64.toByteArray(fs.readFileSync('../src/js/somePath/inLibrary/Private/file1.afm', 'base64'));
对于每个文件。我想用正确的包路径替换该路径,但 __dirname
没有帮助。这就是为什么我想使用 callsites.
我想做的是将 callsites 作为全局依赖项插入到我的包中,并像 __webpack_require__(moduleId)
一样使用它,这样我就可以拉入正在执行的 js 文件路径(__dirname
或 __filename
不起作用)
所以理论上我会插入 callsites()[0].getFileName() + __webpack_require__(moduleId)
到目前为止我的配置是这样的,webpack-file-resolver
是我正在做的当前插件:
const path = require('path')
const webpackTs = require('webpack-config-typescript')
var WebpackFileResolver = require('webpack-file-resolver')
let config = {
entry: path.join(__dirname, 'src/handler.ts'),
target: 'node',
output: {
filename: 'deploy/handler_[hash].js',
libraryTarget: 'commonjs',
path: path.join(__dirname)
}
}
config = webpackTs.ts(config)
config.module.rules.push({
test: /\.(ttf|trie|afm)$/,
loader: "file-loader",
options: {
name: "[name].[ext]",
outputPath: "deploy",
publicPath: "./"
},
})
config.plugins.push(new WebpackFileResolver({
test: /\.(trie|afm)$/,
serverPath: "./"
}))
module.exports = config
到目前为止,这是我得到的:
const ConcatSource = require("webpack-sources").ConcatSource
function getRequires (options, chunks) {
return chunks.reduce((c, chunk) => {
chunk.forEachModule((module) => {
const deps = module && module.fileDependencies && module.fileDependencies || []
deps.forEach((filepath) => {
if(options.test.test(filepath)) {
c.add({
path: filepath,
id: module.id
})
}
})
})
return c
}, new Set())
}
class WebpackFileResolverPlugin {
constructor(options = {}) {
this.options = options
}
apply(compiler) {
const options = this.options
compiler.plugin('compilation', (compilation) => {
compilation.plugin('optimize-chunk-assets', (chunks, done) => {
const requires = getRequires(options, chunks)
replaceBundleReadDir(compilation, chunks, requires)
done()
})
})
}
}
function replaceBundleReadDir(compilation, chunks, requires){
chunks.forEach(function (chunk) {
chunk.files.forEach(function (fileName) {
replaceSource(compilation, fileName, requires)
})
})
}
function replaceSource(compilation, fileName, requires){
let result = compilation.assets[fileName].source()
const source = []
requires.forEach((require) => {
let buffer = []
for (let c of result) {
if (c !== '\n') {
buffer.push(c)
} else {
const line = buffer.join('')
const newLine = replaceFsReadDir (require, line)
if (newLine !== undefined) {
result = result.replace(line, newLine)
}
buffer = []
}
}
})
compilation.assets[fileName] = new ConcatSource(result)
}
function replaceFsReadDir (require, line) {
const webpackRequire = '__webpack_require__'
const fileName = require.path.replace(/^.*[\\/]/, '')
const fileStartMarker = line.indexOf(fileName)
const readDirMarker = line.lastIndexOf('readFile')
if (fileStartMarker !== -1 && readDirMarker !== -1) {
let fileEndMarker = line.indexOf(')', fileStartMarker)
let getEnd = line.slice(fileStartMarker, fileEndMarker + 1)
fileEndMarker = (getEnd.length > fileName.length + 2) ? line.indexOf(',', fileStartMarker) : fileEndMarker
const startSlice = line.indexOf('(', readDirMarker) + 1
const newLine = `${line.slice(0, startSlice)}${webpackRequire}(${require.id})${line.slice(fileEndMarker)}`
return newLine
} else {
return undefined
}
}
module.exports = WebpackFileResolverPlugin
同时我将使用以下内容,它非常老套,所以我不能真正推荐它。
我所做的是将我的全局函数添加到我的包中,然后将路径替换为当前正在执行的路径 javascript。如有任何想法,我们将不胜感激。
const ConcatSource = require("webpack-sources").ConcatSource
// This is the function I want to use on my bundle
const noRestForTheWicked = `
const __callsites__ = () => {
const _ = Error.prepareStackTrace;
Error.prepareStackTrace = (_, stack) => stack;
const stack = new Error().stack.slice(1);
Error.prepareStackTrace = _;
return stack;
}
const __current_file__ = () => {
const sep = require('path').sep
let filePieces = __callsites__()[0].getFileName().split(sep)
return filePieces.slice(0, -1).join(sep) + sep
};
`
function getRequires (options, chunks) {
return chunks.reduce((c, chunk) => {
chunk.forEachModule((module) => {
const deps = module && module.fileDependencies && module.fileDependencies || []
deps.forEach((filepath) => {
if(options.test.test(filepath)) {
c.add({
path: filepath,
id: module.id
})
}
})
})
return c
}, new Set())
}
class WebpackFileResolverPlugin {
constructor(options = {}) {
this.options = options
}
apply(compiler) {
const options = this.options
compiler.plugin('compilation', (compilation) => {
compilation.plugin('optimize-chunk-assets', (chunks, done) => {
const requires = getRequires(options, chunks)
replaceBundleReadDir(compilation, chunks, requires, options)
done()
})
})
}
}
function replaceBundleReadDir(compilation, chunks, requires, options){
chunks.forEach(function (chunk) {
chunk.files.forEach(function (fileName) {
replaceSource(compilation, fileName, requires, options)
})
})
}
function replaceSource(compilation, fileName, requires, options){
let result = compilation.assets[fileName].source()
if ('serverPath' in options && options.serverPath !== undefined) {
// This is where the hacking happens
result = noRestForTheWicked + result
}
requires.forEach((require) => {
let buffer = []
for (let c of result) {
if (c !== '\n') {
buffer.push(c)
} else {
const line = buffer.join('')
const newLine = replaceFsReadDir (require, line, options)
if (newLine !== undefined) {
result = result.replace(line, newLine)
}
buffer = []
}
}
})
compilation.assets[fileName] = new ConcatSource(result)
}
function replaceFsReadDir (require, line, options) {
const webpackRequire = '__webpack_require__'
const fileName = require.path.replace(/^.*[\\/]/, '')
const fileStartMarker = line.indexOf(fileName)
const readDirMarker = line.lastIndexOf('readFile')
if (fileStartMarker !== -1 && readDirMarker !== -1) {
let fileEndMarker = line.indexOf(')', fileStartMarker)
let getEnd = line.slice(fileStartMarker, fileEndMarker + 1)
fileEndMarker = (getEnd.length > fileName.length + 2) ? line.indexOf(',', fileStartMarker) : fileEndMarker
const startSlice = line.indexOf('(', readDirMarker) + 1
let importStr = `${webpackRequire}(${require.id})`
if ('serverPath' in options && options.serverPath !== undefined) {
// Server Land, brace for impact, inserting the thing
importStr = `__current_file__() + ${importStr}`
}
const newLine = `${line.slice(0, startSlice)}${importStr}${line.slice(fileEndMarker)}`
return newLine
} else {
return undefined
}
}
module.exports = WebpackFileResolverPlugin