extract-loader
extract-loader copied to clipboard
Supporting js extraction?
I am new to webpack and might have a slippery grasp on how this all works exactly, but seeing as my index.html
had a <script src="js/main.js">
tag in it, I figured it wouldn't be unreasonable for the loader to see this tag and extract the source into the build directory appropriately, but discovered that it was just evaluating the contents of it instead and outputting nothing, causing build errors. In the source it looks like this could be fixed by just changing the test for node evaluation to be /css-base\.js$/
. Or is that not how this is meant to be used?
I forked, made the change, and all tests are still passing. Pull request to follow.
I'm sorry, the extract-loader has really been designed to cope with the css-loader and the html-loader. If you're doing more sophisticated stuff, you're better off with the extract-text-webpack-plugin.
Or did the proposed change (from your PR) help your use-case?
@heptahedron : I'm stuck since many days trying to extract JS (script) files from HTML. Here is my attemp to get help on Stackoverflow.
@jhnns : Do you have any suggestion on how to use extract-text-pluging to achieve what we need ? I saw some PR related to this issue like #7, #20. Are they fixing the problem ? I applied those patch on my extractLoader.js
from the node_modules folder but I'm now getting the error ReferenceError: require is not defined
while parsing the javascript file.
Here is the only line that my javascript contains :
var $ = require("jquery");
@purell It's currently not possible with webpack to import a JavaScript file into an HTML file (via <script src
).
This is because webpack has been designed as JavaScript bundler. Other file types, like CSS and HTML, need to be translated to JavaScript modules first. Unfortunately, this kind of import (JS into HTML) is not easy to achieve with the current architecture. However, we're looking for ways to treat CSS and HTML as first-class citizens, but for now I just can say that this is impossible 😞.
Its not impossible, just hard, you can create a loader that uses emitFile to emit the JS and remove it from the HTML. Its doable using the posthtml, its similar to what I did in the other post about removing the CSS, its the same problem. Perhaps html-loader could do this for us, someone could ping them.
Here is what I am doing.
function extract_js (content, loaderContext) {
try {
const loaderUtils = require('loader-utils');
const posthtml = require('posthtml');
return posthtml()
.use(tree => {
if (tree.length === 0) return tree;
return tree.match([
{ tag: 'script' }
], node => {
const content = node.content;
const url = loaderUtils.interpolateName(this, '[hash:26]c0ffee.js', {
content,
});
loaderContext.emitFile(url, content)
node.tag = false;
return node;
});
})
.process(content, { sync: true })
.html;
} catch (error) {
loaderContext.emitError(error);
return content;
}
}
function filter_extracted (tag, attribute, attributes) {
return !(attributes[attribute] && attributes[attribute].indexOf('c0ffee') !== -1);
}
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [{
loader: 'babel-loader',
options: CONFIG.babel,
}]
},
{
test: /\.template$/,
use: [{
loader: 'raw-loader',
}, {
loader: 'extract-loader',
}, {
loader: 'html-loader',
options: {
minimize: true,
attributes: {
root: resolve(CONFIG.assetsDir),
list: [
{
tag: 'script',
attribute: 'type',
type: 'src',
filter: filter_extracted_js,
}
],
},
preprocessor: extract_js,
}
}]
}
]
},
}