dc7290 / template-ejs-loader

ejs-loader with webpack5 support. Chain it to html-loader and use it with html-webpack-plugin.
MIT License
24 stars 3 forks source link

"Passing individual values" config output errors #11

Closed florent-cdl closed 2 years ago

florent-cdl commented 2 years ago

Hi, I'm trying to get the current filename inside my ejs template (which include an ejs with that name) but can't get that parameter either by HtmlWebpackPlugin options or template-ejs-loader.

This is a part of my webpack.config (plugins part, sorry some quotes don't render ,so have to change "`" to "'") :

...arrayOfEntry.map( (page) => new HtmlWebpackPlugin({ inject: true, template: '${projectPaths.projectEjsTemplatesPath}/webpack-base-standard.ejs', filename: '../${page}.html', chunks: [page, "common"], templateParameters: { env: process.env.NODE_ENV, jsPath: projectPaths.projectJsPath, cssPath: projectPaths.projectScssPath, ejsPath: projectPaths.projectEjsPath, filename: page }, }) ),

filename templateParameters always set to the first 'page' var opf the loop I've tried (as specified in readme file)

template: '!${require.resolve('html-loader')}??ruleSet[1].rules[0].use[0]!${path.resolve( __dirname, '../lib/index.js' )}?${new URLSearchParams({ // Use the query as an option to pass to the loader root: projectPaths.projectEjsTemplatesPath, data: JSON.stringify({ foo: 'bar', }), })}!${projectPaths.projectEjsTemplatesPath}/webpack-base-standard.ejs',

but get the error ERROR in Error: Child compilation failed: Module not found: Error: Can't resolve '/Volumes/TEST-WEBPACK/lib/index.js' in '/Volumes/TEST-WEBPACK'

Please if someone get the solution. What I'm trying to get inside the template ejs

<%- include('${htmlWebpackPlugin.options.ejsPath}/${htmlWebpackPlugin.options.filename}.ejs', {myvar : 'test'}) %>

Best regards Florent

dc7290 commented 2 years ago

@florent-cdl

Hello. Thank you for using our library here!

Could you please create a sample project to reproduce the error? Or please attach webpack.config.js.

We might be able to figure out if the error is caused by html-webpack-plugin, template-ejs-loader, or something else. or something else.

florent-cdl commented 2 years ago

Hi,

What I want to do is :

I managed to get that filename but was obliged to modify your loader : I've added that line (after line 70 of node_modules/template-ejs-loader/lib/index.js ) filename: Object.keys(this._compiler?.options.entry)[0] but can't keep such a solution that will be erase in update

My webpack.config.js is quite long but here is (at the message bottom) a brief view.

I just resumed entries with 2 lines but this part is a loop on multiple files like the HTMLWebpackPlugin part.

Your loader doesn't allow templateParameters as a function (but not sure it is the solution)

A more simple HTMLWebpackPlugin version I test never give me the right filename but always the first one used on the loop (event if filename is the right one in the loop below)

new HtmlWebpackPlugin({ inject: true, template:${projectPaths.projectEjsTemplatesPath}/webpack-base-standard.ejs, filename:../${page}.html, chunks: [page, "common"], templateParameters: { env: process.env.NODE_ENV, jsPath: projectPaths.projectJsPath, cssPath: projectPaths.projectScssPath, ejsPath: projectPaths.projectEjsPath, filename: page }, })

So I tested this one to have singular parameter :

new HtmlWebpackPlugin({ inject: true, // template:${projectPaths.projectEjsTemplatesPath}/webpack-base-standard.ejs, template:!${require.resolve('html-loader')}??ruleSet[1].rules[0].use[0]!${path.resolve( __dirname, '../node_modules/template-ejs-loader/lib/index.js' )}?${new URLSearchParams({ // Use the query as an option to pass to the loader root: projectPaths.projectOutput, data: JSON.stringify({ filename: page }), })}!${projectPaths.projectEjsTemplatesPath}/webpack-base-standard.ejs, filename:../${page}.html, chunks: [page, "common"], templateParameters: { env: process.env.NODE_ENV, jsPath: projectPaths.projectJsPath, cssPath: projectPaths.projectScssPath, ejsPath: projectPaths.projectEjsPath, filename: page }, })

{ mode: 'development', devServer: { static: { directory: '/Volumes/TRAVAUX/PROJETS/TEST-WEBPACK/dist' } }, entry: { 'about-us': '/Volumes/TRAVAUX/PROJETS/TEST-WEBPACK/src/bundles/js/about-us.js', 'account-credit-card-create': '/Volumes/TRAVAUX/PROJETS/TEST-WEBPACK/src/bundles/js/account-credit-card-create.js' }, output: { chunkFilename: '[id].chunk.js', path: '/Volumes/TRAVAUX/PROJETS/TEST-WEBPACK/dist/js', assetModuleFilename: 'images/[hash][ext][query]', filename: '[name]-modern.js' }, resolve: { extensions: [ '*', '.js', '.jsx' ], alias: { handlebars: 'handlebars/dist/handlebars.js' }, modules: [ '/Volumes/TRAVAUX/PROJETS/TEST-WEBPACK/node_modules' ] }, devtool: false, module: { rules: [ { test: /\.ejs$/, use: [ { loader: 'html-loader', options: { // Disables attributes processing sources: false, }, }, { loader: 'template-ejs-loader', options: {data: {test:'true'}} } ], } ] }, name: 'client-modern', target: 'browserslist:modern',

florent-cdl commented 2 years ago

Hi, do you find some resolutions ? or ways to have the filename parameters inside the ejs ?

Thank you

florent-cdl commented 2 years ago

Hi, I'm interested having your knowledge on that point because i'm really stopped and can't find a solution right now Thank you

mizok commented 2 years ago

@florent-cdl Uh.. I guess you need to describe your question more clearly, since you are not able to give a reproducible repository. (bc even me don't understand what the problem is...)

And if you want to show your .js code, you can use

img

florent-cdl commented 2 years ago

Hi, It's very simple : How can I get the current filename inside my ejs template ? As I want to include an ejs which has the same name as the filename being process (but in another template part directory) Thank you

mizok commented 2 years ago

@florent-cdl

You mean ... just like this?

folder structure:

root
├── index.ejs
├── partials1
               └──── tempA.ejs
└── partials2
               └──── tempA.ejs

index.ejs:

<%- include "./partials1/tempA.ejs" %>
<%- include "./partials2/tempB.ejs" %>
mizok commented 2 years ago

I guess I know what you are meaning about. You got all your htmlWebpackPlugin instances generated within a loop, and you want to get current filename(when iterated) inside your .ejs template as a variable right? (But this seems to be a weird using condition, at least it is to me :neutral_face: )

florent-cdl commented 2 years ago

This is exactly the pb. We have a complex site with lot of ejs files and includes So do you know how to get that value ?

mizok commented 2 years ago

@florent-cdl

I don't think there is an existing way(using this loader) for your problem. And I am not sure if @dc7290 is busy by this time :( (It's Asian new year time now.) I did try to contact him using twitter, but no luck.

Even I get a solution, I still have to wait for the reviewing of my pull request. (I also had my pull request commited, but still not get contacted.)

Actually I am thinking about creating a new ejs loder npm package on my own BTW :/

florent-cdl commented 2 years ago

Great ! Thank you very much I will wait your message Have a nice day

mizok commented 2 years ago

@florent-cdl

I think I got a temporary solution for you, but not with this loader. You can try ejs-loader as an alternative.(I have already tested this in my Webapck 5 template repo.) then you can just use the option templateParameters of htmlWebpackPlugin like below:

new HtmlWebpackPlugin({
    filename: ...,
    template: ...,
    templateParameters:{
      filename://  filename you get.
    }

  })

And in .ejs file:

<!DOCTYPE html>
<html lang="en">

<head></head>

<body>
  <div class="site">
    <div class="site__header-wrapper">

    </div>
    <div class="site__body">
      <!-- use temaplateParameter-->
      <h1><%= htmlWebpackPlugin.options.filename %></h1>
    </div>
    <div class="site__footer-wrapper">
       <!-- include other partial-->
      <%= require('./src/template/footer.ejs')() %>
      <!-- no using alias -->
      <img src="./assets/images/xxx.png">
    </div>
  </div>

</body>

</html>

PS.But if you decide to use ejs-loader, you will have to give up using html-loader(bc they conflict), which means your webpack ejs module rule will become like this:

{
        test: /\.ejs$/,
        use: [// no other loader except ejs-loader
          {
            loader: 'ejs-loader',
            options: {
              esModule:false
            }
          }
        ]
      },

And ONCE you remove html-loader, it means:

florent-cdl commented 2 years ago

Hi Thank you for the solution I've already tried lot of ejs loaders, and this one. I can't remember the pb with this one but I will give it a try and get back to you. And otherwise, the evoution I give in my previous messages ? : _I managed to get that filename but was obliged to modify your loader : I've added that line (after line 70 of node_modules/template-ejs-loader/lib/index.js ) filename: Object.keys(this.compiler?.options.entry)[0] but can't keep such a solution that will be erase in update Best regards

mizok commented 2 years ago

It's not "my loader"... pal lol. I am just another user trying to fix things up haha.

If you do have some good idea about fixing this issue, I suggest you just make a pull request. And once your pull request get accepted, your modification will get merge into this package, and it won't be erased again even you do npm install.

But about the message you mentioned above, I don't think that's a good way to go, 'cause not everyone using this loader will need that filename variable, so it may not be accepted by the author if you make this as a pull request I guess.

dc7290 commented 2 years ago

@mizok Thank you for offering a solution on my behalf.

florent-cdl commented 2 years ago

Hi d-suke, What do you think of the solution I give, : adding this line (after line 70 of node_modules/template-ejs-loader/lib/index.js ) : filename: Object.keys(this.compiler?.options.entry)[0] Or perhaps you have another solution ? Thank you

dc7290 commented 2 years ago

@florent-cdl

Sorry for the late reply.

I still do not understand the problem you are having. Are you saying that you want to pass different values to each ejs file?

florent-cdl commented 2 years ago

I just want to get the current filenmane as a variable inside the ejs. I've tried the way with "queryString.stringify" but without success (as you can see in my first message) My webpack file is quite complex, htmlwebbpack inside a loop. No way to get that filename and use it inside the ejs template

mizok commented 2 years ago

@dc7290 I just made another pull request for you about this issue. you can check it.

mizok commented 2 years ago

@florent-cdl
You can now update to v.0.7.0 for this issue.(And you can check README.md for the solution) Though the new solution is not using your idea, I fixed the old method, bc I confirmed that there was something wrong about the entry path, and obviously we need an upgrade for the URLsearchParams issue. I have already tested this change in my product repository, and it worked fine.

If you still have any problem, just feel free to report a new issue.

florent-cdl commented 2 years ago

Very nice, you're the best :) I will give it a try tomorrow. Best regards