Git Product home page Git Product logo

ejs-loader's Introduction

Deprecated

Please use new Webpack 5 compatible loader: https://github.com/dc7290/template-ejs-loader (https://www.npmjs.com/package/template-ejs-loader)

ejs-loader for webpack

npm Build Status

EJS (Underscore/LoDash Templates) loader for webpack. Uses lodash template function to compile templates.

If you are looking for the loader which uses EJS templating engine, there is ejs-compiled-loader

Installation

npm install ejs-loader

Usage

Documentation: Using loaders

var template = require("ejs!./file.ejs");
// => returns the template function compiled with underscore (lodash) templating engine.

// And then use it somewhere in your code
template(data) // Pass object with data

You also should provide a global _ variable with the lodash/underscore runtime. You can do it with the following webpack plugin: https://github.com/webpack/docs/wiki/list-of-plugins#provideplugin

plugins: [
    new webpack.ProvidePlugin({
        _: "underscore"
    })
]

Options

Underscore/Lodash options can be passed in using the querystring or adding an esjLoader options block to your configuration.

Config example with Webpack 4+

module.exports = {
  module: {
    rules: [
      {
        test: /\.ejs$/,
        loader: 'ejs-loader',
        options: {
          variable: 'data',
          interpolate : '\\{\\{(.+?)\\}\\}',
          evaluate : '\\[\\[(.+?)\\]\\]'
        }
      }
    ]
  }
};

Config example using a querystring (deprecated):

module.exports = {
  module: {
    loaders: [
      { test: /\.ejs$/, loader: 'ejs-loader?variable=data' },
    ]
  }
};

is equivalent to

var template = _.template('<%= template %>', { variable : 'data' });
module.exports = {
    module: {
        loaders: [
            {
                test: /\.ejs$/,
                loader: 'ejs-loader',
                query: {
                    variable: 'data',
                    interpolate : '\\{\\{(.+?)\\}\\}',
                    evaluate : '\\[\\[(.+?)\\]\\]'
                }
            },
        ]
    }
};

is equivalent to

var template = _.template('<%= template %>', { variable: 'data', interpolate : '\\{\\{(.+?)\\}\\}', evaluate : '\\[\\[(.+?)\\]\\]' });

Config example using the ejsLoader config block (deprecated):

module.exports = {
  module: {
    loaders: [
      { test: /\.ejs$/, loader: 'ejs-loader' }
    ]
  },
  ejsLoader : {
    variable    : 'data',
    interpolate : /\{\{(.+?)\}\}/g,
    evaluate    : /\[\[(.+?)\]\]/g
  }
};

Export as CommonJS

By default, ejs-loader generates JS modules that use the ES modules syntax. There are some cases in which using ES modules is beneficial, like in the case of module concatenation and tree shaking.

You can enable a CommonJS module syntax using:

Config example with Webpack 4+

module.exports = {
  module: {
    rules: [
      {
        test: /\.ejs$/,
        loader: 'ejs-loader',
        options: {
          esModule: false
        }
      }
    ]
  }
};

The variable option is required to compile EJS templates into ES compatible modules. If the variable option is not provided as a loader or query option, an Error will be thrown. Please see lodash/lodash#3709 (comment) for additional details.

Including nested templates

Lodash template function does not provide include method of ejs module. To include other templates, passing template functions as parameters does the job. For example:

index.js:

var mainTemplate = require('ejs!./main.ejs');
var hyperlinkTemplate = require('ejs!./hyperlink.ejs');
var renderedHtml = mainTemplate({ hyperlink: hyperlinkTemplate });

main.ejs:

<h1><%= hyperlink({ name: 'Example', url: 'http://example.com' }) %></h1>

hyperlink.ejs:

<a href="<%= url %>"><%= name %></a>

As a result, renderedHtml becomes a string <h1><a href="http://example.com">Example</a></h1>.

Release History

  • 0.5.0 - Changed exportAsESM flag to esModule and enabled this behavior by default to be consistent with other webpack loaders.
  • 0.4.1 - Add default object for options to prevent breakages when the webpack query object is null
  • 0.4.0 - Add support for ESModules with the exportAsESM flag
  • 0.3.5 - Fix dependency vulnerabilities.
  • 0.3.3 - Fix dependency vulnerabilities.
  • 0.3.0 - Allow passing template options via ejsLoader or via loader's query
  • 0.2.1 - Add ability to pass compiller options
  • 0.1.0 - Initial release

License

MIT (http://www.opensource.org/licenses/mit-license.php)

ejs-loader's People

Contributors

adifelice-godaddy avatar atofstryker avatar axelpale avatar bemjb avatar dependabot[bot] avatar difelice avatar ebuster avatar gerhut avatar helloint avatar knisterpeter avatar mj111 avatar okonet avatar thraxil avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

ejs-loader's Issues

_ must be available globally for compiled templates to work?

  1. Load Underscore w. webpack, such that it isn't exposed globally
  2. Compile a template with ejs-loader
  3. Try to use that template in your code
Uncaught ReferenceError: _ is not defined.
module.exports = function (obj) {
obj || (obj = {});
var __t, __p = '', __e = _.escape;
with (obj) {
__p += '<div>myTemplate</div>';

}
return __p
}

"not a loader" error in webpack 2.1.0-beta.27

Does this mean that the latest webpack is not supported?

The message:

throw new Error("Module '" + loader.path + "' is not a loader (must have normal or pitch function)");
^

Error: Module '/path/to/loader/ejs' is not a loader (must have normal or pitch function)

"Cannot use import statement outside a module" error when import statement is used inside template

I can't use import statement inside ejs template. esModule option of ejs-loader loader is set to true. And I am facing the "Cannot use import statement outside a module" error.

<%
  import example from '../components/example/example.ejs'
%>

<div class="container">
  <%= example({ title: 'Some title' }) %>
</div>

My guess is that this is due to the import being inside a function, which is not the correct syntax:

export default function(props) {
  //...
  import example from '../components/example/example.ejs'
  //...
}

Is it possible to move the import statements to the top level of the generated es module?

parseQuery() will be replaced with getOptions() in the next major version of loader-utils.

When using ejs-loader I get the following warning:

loaderUtils.parseQuery() received a non-string value which can be problematic, see #webpack/loader-utils#56
parseQuery() will be replaced with getOptions() in the next major version of loader-utils.

Stacktrace when setting process.traceDeprecation = true:

DeprecationWarning: loaderUtils.parseQuery() received a non-string value which can be problematic, see webpack/loader-utils#56
parseQuery() will be replaced with getOptions() in the next major version of loader-utils.
at Object.parseQuery (node_modules\ejs-loader\node_modules\loader-utils\index.js:78:3)
at Object.module.exports (node_modules\ejs-loader\index.js:6:27)
at LOADER_EXECUTION (node_modules\loader-runner\lib\LoaderRunner.js:119:14)
at runSyncOrAsync (node_modules\loader-runner\lib\LoaderRunner.js:120:4)
at iterateNormalLoaders (node_modules\loader-runner\lib\LoaderRunner.js:229:2)
at Array. (node_modules\loader-runner\lib\LoaderRunner.js:202:4)
at Storage.finished (node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:38:15)
at node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:69:9
at node_modules\graceful-fs\graceful-fs.js:78:16
at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:416:3) Hash: ee67b5e6804e7d7cc798
Version: webpack 2.3.2`

Versions:
ejs-loader@^0.3.0:
version "0.3.0"

loader-utils@^0.2.15, loader-utils@^0.2.16, loader-utils@^0.2.7:
version "0.2.17"

Webpack 4 Support

Description
ejs-loader causes an error on Webpack 4 when using webpack-contrib/html-webpack-plugin.

Config

  new HtmlWebpackPlugin({
      template: `!!ejs-loader!src/main.html`,
      xhtml: true,
      inject: 'body',
      cordova: process.env.device_target !== undefined
  }),

Log

ERROR in ./node_modules/ejs-loader!./src/main.html                                                
Module build failed: TypeError: Cannot read property 'ejsLoader' of undefined

template(data) get a string?

when i pass data to template by template(data), i get a string like module.exports = function anonymous(locals, escape, include, rethrow) {...

but, i expect it return a html pice, can you tell me how to do? thank you very mush.

How to set templateSettings like in requireJS?

I am working on moving a project from requireJS to webpack. Your loader has been a great help (thanks!).

I have some code that uses mustache style templates. They load fine do not render right.
In the orginal requireJS file it set the templatesSettings:

    templateSettings: {
        evaluate : /\{\[([\s\S]+?)\]\}/g,
        interpolate : /\{\{([\s\S]+?)\}\}/g
    }

Is there a way to pass this configuration in in webpack.config.js?

how to process image.src in ejs?

I have index.js with code:

let tpl = require('./tpl.ejs');
let dom = tpl()

But tpl.ejs has <image src="./a.jpg">, so how to make it as jsx does? thanks.

ejs include example: just add a small function

webpack.config.js: (module.exports.plugins[])
new HtmlWebpackPlugin({
template: 'src/templates/a.ejs',
filename: 'build/a.html'
})

a.ejs:

<% var inc = function(name, sendData){
return require('./' + name + '.ejs')(sendData ? {data: data} : null);
}; %>

<% var data = require('path/to/data.js'); %>

<!doctype html>
<html><body>
...
<%=inc('b', true) %>
...
</body></html>

b.ejs:

<h1><%=data.title %><h1>

"not a loader" error in webpack ^4.6.0

node_modules\loader-runner\lib\loadLoader.js:35
throw new Error("Module '" + loader.path + "' is not a loader (must have normal or pitch function)");

Error: Module 'node_modules\ejs\lib\ejs.js' is not a loader (must have normal or pitch function)

Trying to use it like this:

new HtmlWebpackPlugin({
      inject: false,
      hash: true,
      template: '!!ejs!./views/index.ejs'
}),

Maybe this can help - https://medium.com/webpack/webpack-4-migration-guide-for-plugins-loaders-20a79b927202

import 'lodash'

Do you really need to import the whole lodash library instead of specific import?

import template from 'lodash/template';

image

Because I use only couple lodash methods in my app.

Is webpack 5 supported?

This loader hasn't been updated since last year and doesn't seem to support webpack 5.

For example, I could not find a solution for my problem of using ejs-loader and html-loader at the same time.
My current config with webpack 4 is something like:

{
    test: /\.ejs$/i,
    use: [
        {
            loader: 'ejs-loader',
            options: {
                variable: 'data',
            }
        },
        'extract-loader',
        'html-loader',
    ]
}

First, I process the ejs files through html-loader so that the webpack knows about static files (img src="/something.jpg", etc.). Then I pass output to extract-loader, which extracts the module back to html/ejs strings. Then the processed .ejs passed into ejs-loader.

html-loader >= 2.0 exports HTML as modules, added new URL syntax and uses parse5 for parsing ejs files.
Next, extract-loader is not supported since May 2020 and is therefore not compatible with webpack 5. html-loader has an idea to add an option for similar functionality, this will partially solve the problem of extract-loader.
But even after that, it will not be possible to use html-loader anymore, since now it checks html tags more strictly and it will not allow to use ejs templates as before.

A simple example of how it is used now (data comes from the backend):

<span>Hello, <%- data.username %></span>
<img src="/images/user.jpg">
import template from "templates/sample.ejs";

// process response from backend
let output = template({ username: response.username });

Therefore, the question is how to similarly use webpack 5 with compiled ejs templates, while pre-processing the source templates to process them to the webpack (which is what the html-loader is doing now). Developers of html-loader says that other loaders like ejs-loader should do this, and html-loader loader will only support correct html tags.

Necessity of ProvidePlugin

Continuation of #28.

@KnisterPeter This line ...

https://github.com/okonet/ejs-loader/blob/4dbd9db88197c3c9d6bd60bb4f3ddea528767cfa/index.js#L23

... compiles a template during a Webpack build, so "this loader does not compile anything at compile time" seems factually incorrect to me. However, yes, it does produce code dependent on _.escape, and it's unfortunate that I have to use ProvidePlugin to supply the _.

A better approach, IMO, would be to have a loader option taking the name of the module to use ("lodash" or "underscore"), and supplying it to the template compiler via the imports option, preferably defaulting to "lodash". Inlining _.escape would be even better, but that isn't trivial to achieve correctly.

Why do I open an issue here, instead of just using ejs-compiled-loader? Well, I'm using it, for now, but I'd prefer to use this loader, since it has fewer dependencies and uses Lodash.

Fails in strict mode

Module build failed: SyntaxError: <path> 'with' in strict mode
lodash's template uses with.

Is there any workaround? I'm surprised that I'm the only one with this issue.

{
    test: /\.ejs/,
    loader: 'ejs-loader',
    include: path.join(sourceDir, '_assets', 'javascripts', 'templates')
}

Using import 'template_name.ejs' to include it.

reversed <%- %> and <%= %>

Escaped output with <%= %> (escape function configurable)
Unescaped raw output with <%- %>

but my test results is reversed

test code:

<div><%- '<img/>'%></div>

results:

<div>&lt;img/&gt;</div>

the write results should be:

<div><img/></div>

Escaping HTML Syntax error

I am using the loader with the HtmlWebpackPlugin
If I don't use escaping it is working perfectly fine.
But as soon as I tried to use <%- %> I have issues.
First of all, I got an error "_ is not defined" so I added it a compile time

new webpack.DefinePlugin({
    _: require('lodash')
})

Now I get a weird error message:

var __t, __p = '', __e = ().escape, __j = Array.prototype.join;
                          ^
  SyntaxError: Unexpected token 

It seems that lodash is replaced by () instead of _

If try to use lodash manually to escape:

<%= _.escape(myString) %>

I get the same error:

((__t = ( ().escape(compilation.assets[path].source()) )) == null ? '' : __t) +

Is It possible to get compiled html using only require?

Hello, I'm sorry for this question, but need to include compiled ejs that was modified through loader chain.
For example I want code looks like this to output compiled ejs with better indents.
<%= require('better-indents-loader!raw-loader!ejs-loader?{'+data+'}!./myEjs.ejs').default %>
Is that possible?

Why lodash instead of ejs?

Is there a special reason why you're using lodash instead of ejs? I need to use filters which are not available on lodash. Would be cool to configure those via loader queries.

The use of this package generates error with htmlwebpackplugin

reference this plugin on webpack configuration generates this output

ERROR in Template execution failed: ReferenceError: htmlWebpackPlugin is not defined

ERROR in   ReferenceError: htmlWebpackPlugin is not defined

  - loader.js:4 module.exports
    /home/alex/code/video-test/src/index.ejs?./~/html-webpack-plugin/lib/loader.js:4:11

  - index.js:255 
    [video-test]/[html-webpack-plugin]/index.js:255:16

  - util.js:16 tryCatcher
    [video-test]/[bluebird]/js/release/util.js:16:23

  - promise.js:504 Promise._settlePromiseFromHandler
    [video-test]/[bluebird]/js/release/promise.js:504:31

  - promise.js:561 Promise._settlePromise
    [video-test]/[bluebird]/js/release/promise.js:561:18

  - promise.js:598 Promise._settlePromiseCtx
    [video-test]/[bluebird]/js/release/promise.js:598:10

  - async.js:143 Async._drainQueue
    [video-test]/[bluebird]/js/release/async.js:143:12

  - async.js:148 Async._drainQueues
    [video-test]/[bluebird]/js/release/async.js:148:10

  - async.js:17 Immediate.Async.drainQueues [as _onImmediate]
    [video-test]/[bluebird]/js/release/async.js:17:14

also referenced here:
jantimon/html-webpack-plugin#323

Passing function to imported ejs

Earlier without webpack ejs-loader, using the lodash

ejs template was

<h1>USER NAME</h1>
<%- func(userName) %>
import inputTemplate from 'template.ejs'
var templateOptionsObj = {
      imports: {
        func: function func(str) {
          return str.toUpperCase();
        }
      }
    }

    var template = _.template(inputTemplate, templateOptionsObj);
    $('#divID').append(template(data));

Now i am using ejs-loader with webpack

import inputTemplate from 'template.ejs' // is already returning exicuted value of  _.template(inputTemplate);

var templateOptionsObj = {
    imports: {
      func: function func(str) {
        return str.toUpperCase();
      }
    }
  }

var template = inputTemplate(data, templateOptionsObj); // is not woking

i am not able to pass my function to the ejs after importing.

How do i need to import my function into the ejs after importing ejs.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.