Webpack loader to extract HTML and CSS from the bundle by evaluating source code in a fake context
npx @tessl/cli install tessl/npm-extract-loader@3.2.0Extract Loader is a webpack loader that extracts HTML and CSS from the bundle by evaluating source code in a fake context and returning the result as a string. It serves as a lean alternative to extract-text-webpack-plugin and mini-css-extract-plugin, specifically designed to work with html-loader and css-loader to resolve URLs within HTML and CSS files.
npm install extract-loader --save-devExtract-loader is used as a webpack loader, not directly imported in code:
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'file-loader',
'extract-loader',
'css-loader'
]
}
]
}
};// webpack.config.js
module.exports = ({ mode }) => {
const loaders = [{
loader: "css-loader",
options: {
sourceMap: true
}
}];
if (mode === "production") {
loaders.unshift(
"file-loader",
"extract-loader"
);
} else {
loaders.unshift("style-loader");
}
return {
mode,
entry: require.resolve("./app/main.css"),
module: {
rules: [
{
test: /\.css$/,
use: loaders
}
]
}
};
};// webpack.config.js
module.exports = {
entry: [
require.resolve("./app/main.js"),
require.resolve("./app/index.html")
],
module: {
rules: [
{
test: /\.html$/,
use: [
"file-loader",
"extract-loader",
{
loader: "html-loader",
options: {
attrs: ["img:src", "link:href"]
}
}
]
},
{
test: /\.css$/,
use: [
"file-loader",
"extract-loader",
"css-loader"
]
}
]
}
};Extract-loader operates by:
babel-preset-env targeting current Node.js versionbabel-plugin-add-module-exports for CommonJS interoperabilitybabelrc: false to ignore project babel configurationThe main webpack loader function that processes source code in a fake context.
/**
* Webpack loader function that extracts content by evaluating source in a fake context
* @param {string} src - Source code to process
* @this {LoaderContext} Webpack loader context (required)
* @returns {void} Uses webpack's async callback pattern via this.async()
*/
async function extractLoader(src);Configuration options passed to the extract-loader.
interface ExtractLoaderOptions {
/**
* Public path for handling relative paths when extracting to different locations
* Can be a string or function that receives the loader context
*/
publicPath?: string | ((context: LoaderContext) => string);
}Usage with string publicPath:
{
loader: "extract-loader",
options: {
publicPath: "../"
}
}Usage with function publicPath:
{
loader: "extract-loader",
options: {
publicPath: (context) => '../'.repeat(
path.relative(path.resolve('src'), context.context)
.split('/').length
)
}
}Extract-loader integrates with webpack's loader system and expects to be used in a loader chain.
/**
* Webpack LoaderContext interface (subset used by extract-loader)
*/
interface LoaderContext {
/** Mark the loader result as cacheable */
cacheable(): void;
/** Get async callback for returning results */
async(): (error: Error | null, result?: string) => void;
/** Add file as dependency for webpack watching */
addDependency(file: string): void;
/** Load module through webpack's module system */
loadModule(request: string, callback: (error: Error | null, source?: string) => void): void;
/** Absolute path to the resource being processed */
resourcePath: string;
/** Directory containing the resource being processed */
context: string;
/** Webpack options/configuration */
options: object;
/** Webpack 4+ compilation object (may be undefined in older versions) */
_compilation?: {
outputOptions?: { publicPath?: string };
};
}Enable source maps by configuring css-loader:
{
test: /\.css$/,
use: [
"file-loader",
"extract-loader",
{
loader: "css-loader",
options: {
sourceMap: true
}
}
]
}// Programmatic usage pattern
import stylesheetUrl from "file-loader!extract-loader!css-loader!./main.css";
// stylesheetUrl contains the hashed URL to the final stylesheetmodule.exports = (env, argv) => {
const isDevelopment = argv.mode === 'development';
return {
module: {
rules: [
{
test: /\.css$/,
use: [
...(isDevelopment
? ['style-loader']
: ['file-loader', 'extract-loader']
),
'css-loader'
]
}
]
}
};
};