0

I'm trying to create a loader which will just parse the content for this syntax:

{{ 'assets/someimage.png'|theme }}

every matches should be added as a webpack dependency from the root webpack directory without making any change in the final's content (this syntax is needed by the CMS template)

Here is where I've been:

let path = require('path'),
    themeRegex = /\{\{[\s?]*["|'|`](.*[\.[png|jpe?g|gif|ico])["|'|`][\s?]*\|[\s?]*theme[\s?]*\}\}/g;

module.exports = function (content, map, meta) {
    while ((themeFilterRequest = themeRegex.exec(content)) !== null) {
        var srcPath = path.join(this.rootContext, 'src')
        this.resolve(srcPath, './'+themeFilterRequest[1], (err, result) => {
            if (err) throw err
            console.log(result)
        })
    }

    return 'module.exports = [\n' +
        JSON.stringify(content) +
        '\n].join();'
};

but for now, the file isn't loaded, at the right place. It actually is created in my dist folder but only contain the text "assets/someimage.png" in the png extension file...

How to binary load the file?

Thanks!

1 Answers1

1

When you require a file other then js, webpack applies a special loader per each file type (check your webpack config).

From what you've described, file-loader got activated for the image import.

You can use the webpack inline loaders syntax, and specify the exact loader that should handle your requires. !!file-loader!path/to/file.png (The !! at the beginning tells to webpack to run only specified loaders).

const fs = require('fs');
const path = require('path');

module.exports = function (content, map, meta) {
    // parse your content to get a list of paths to files
    filePaths.forEach(fileToLoad => {
       const file = fs.readFileSync(fileToLoad);
       const fileName = path.basename(fileToLoad);
       this.emitFile(fileName, file)
    });

    return content;
};

felixmosh
  • 32,615
  • 9
  • 69
  • 88
  • This could be the good answer if I wanted to write `import '!!any-loader-to-use!${fileToLoad}';` in the final template file but I don't. What I want is to copy the file directly from the loader and let the template as it is. I tried your way, and also with require(), that didn't do the trick... `Error: Cannot find module '!!raw-loader!/media/maz/Windows/Users/maz-/Desktop/www/october-builder/themes/octobercms-tailwindcss-boilerplate/src/assets/images/october.png'` – Romain 'Maz' BILLOIR Jan 13 '20 at 20:46
  • 1
    I've made a mistake, you should not use `raw-loader` for images... Try to remain only the imports without the inline loaders – felixmosh Jan 13 '20 at 20:54
  • Sorry but It doesn't work, I added the import like that: import `content = \`import '${fromRelativePath}'\`+'\n'+content` but nothing is load, I'm using file-loader in my webpack.config.js And also: I don't want the content to be modified, which is actually the case with that rule `content = `import '${fromRelativePath}'`+'\n'+content` What I want is to tell to webpack "this is a dependency, copy the file". I worked around with Plugin but didn't find the way to achieve that... – Romain 'Maz' BILLOIR Jan 13 '20 at 21:26
  • So, you want to copy, so the import should be the same as you import img from js file. it will copy the file to the output dir – felixmosh Jan 13 '20 at 21:30
  • The fact is I'm not in a js file: it's a html one, with some templating stuff. My goal is to avoid to put "<%= require('myimage.jpg') %> in it – Romain 'Maz' BILLOIR Jan 13 '20 at 21:35
  • 1
    How do you load this template? – felixmosh Jan 13 '20 at 21:35
  • HtmlWebpackPlugin – Romain 'Maz' BILLOIR Jan 13 '20 at 21:36
  • 1
    Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/205890/discussion-between-felixmosh-and-romain-maz-billoir). – felixmosh Jan 13 '20 at 21:36