radiocity / twig-html-loader Goto Github PK
View Code? Open in Web Editor NEWTwig to html loader for webpack
License: MIT License
Twig to html loader for webpack
License: MIT License
Hello. Is there any chance to add newly created template to context, so plugin can compile it without reloading build?
What if I have something like Something:folder1:file.html.twig
how can I add that to the namespaces?
Directory setup:
| partials
| --header.html
| --header.html
| layouts
| --base.html
Is there a way to write {% include "partials/header.html" %}
inside my base.html file without having to do {% include "./../partials/header.html" %}
gulp-twig has a base option to set extends/includes relative to the defined option
Hello,
I'm trying to move the tag generate by htmlWebpackPlugin as describe in this example (with ejs template) :
https://github.com/jantimon/html-webpack-plugin/tree/master/examples/custom-insertion-position
I try to do the same with twig-html-loader :
{{ htmlWebpackPlugin.tags.bodyTags }}
but the htmlWebpackPlugin.tags.bodyTags alway is empty
Is there a way to get this variable ?
Many thanks for your help.
hi,
the loader :
const twig = {
test: /\.twig$/,
use: [
'raw-loader',
{
loader: 'twig-html-loader',
options: {
data: context => {
const data = path.join(__dirname, 'data.json');
context.addDependency(data); // Force webpack to watch file
return context.fs.readJsonSync(data, {throws: false}) || {};
},
},
},
],
};
used with :
const generateHTMLPlugins = () =>
glob.sync('./src/pages/**/*.twig').map(dir => {
const filename = path.basename(dir);
return new HTMLWebpackPlugin({
filename: filename.replace('twig', 'html'),
template: path.join(config.root, config.paths.src + '/pages', filename),
});
});
and the templage :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
{{ include('../partials/header.twig') }}
</body>
</html>
thanks in advance for your help!
Hello,
I'm trying to use data from htmlWebpackPlugin options as describe in Writing Your Own Templates section.
I tried to access the object but it's empty:
<h1>{{ htmlWebpackPlugin.options.title }}</h1>
Probably related to #26
Really appreciate your help
Hey there,
I'm not sure if I'm trying to use data option correctly or not but I'm running into some issues. I've been following the readme and I'm using data as this right now:
const data = path.join(contextPath, `${name}.json`);
context.addDependency(data); // Force webpack to watch file
return context.fs.readJsonSync(data, { throws: false }) || {};
This seems to work properly since I get the correctly rendered html string inside my webpack bundle. However, I can not use this for including a .twig
file into my index.twig
.
Using {% include '@components[name].twig' %}
works but it only includes the plain .twig
file without its corresponding data. These are not known to any .twig
file. Only webpack knows about that. Yet I still couldn't figure out a way to get the string out of my webpack bundle and use it in my rendered index.html
.
Am I missing something here? Or is this an intended behaviour? I'd really like to get my rendered templates into my index.html
.
Then I try to add async function, for example:
functions:{
getFileInfo:(value,...args)=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
// get file info from DB
return resolve(JSON.stringify(require("./demo_data/file_data.js")))//info about file
},3000)
})//promise
},//getFileInfo
}
I got error:
NonErrorEmittedError: (Emitted value instead of an instance of Error) TwigException: You are using Twig.js in sync mode in combination with async extensions.
Hello, my structure looks like:
index.html
-_partials/footer.twig
webpack.config.common.js
:
const glob = require('glob');
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HTMLWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const options = require('./src/options');
const generateHTMLPlugins = () =>
glob.sync('./src/**/*.html').map(
dir =>
new HTMLWebpackPlugin({
filename: path.basename(dir), // Output
template: dir, // Input
}),
);
module.exports = {
node: {
fs: 'empty',
},
entry: ['./src/js/app.js', './src/style/main.scss'],
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.bundle.js',
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
query: {
presets: ['env'],
},
},
{
test: /\.(sass|scss)$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
'css-loader',
'postcss-loader',
'sass-loader',
],
},
{
test: /\.html$/,
use: [
'raw-loader',
{
loader: 'twig-html-loader',
options: {
data: options,
},
},
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: '[name].css',
chunkFilename: '[id].css',
}),
new CopyWebpackPlugin([
{
from: './src/static/',
to: './static/',
},
]),
...generateHTMLPlugins(),
],
stats: {
colors: true,
},
devtool: 'source-map',
};
And this does work, however, if i change anything under _partials directory, changes are not being visible in browser.
If i restart webpack-dev-server, changes are pulled in :(
Any ideas what should be changed to make it work?
There is Twig function source which returns the content of a template without rendering it. One useful use of this function is to insert the svg file into the final HTML.
However, this only works if we specify the full path to the inserted file relative to Webpack context.
I.e. let's assume that we have such a file structure
src/
|-- assets/
|-- file.svg
|-- index.twig
|-- index.js
the content of index.twig
looks like this:
<div>{{ source('....') }}</div>
<div>{{ source('./assets/file.svg') }}</div>
then the result HTML contains "Template "./assets/file.svg" is not defined." instead of content of SVG file<div>{{ source('assets/file.svg') }}</div>
then the result HTML contains "Template "assets/file.svg" is not defined." instead of content of SVG file<div>{{ source('src/assets/file.svg') }}</div>
then the result HTML contains content of SVG fileFiles to reproduce this behavior are attached.
Any ideas how to fix this?
// webpack.config.js
// ...
namespaces: {
'layouts': `${src}/twig/layouts`,
'components': `${src}/twig/components`,
},
// ...
{% import "@components/footer.twig" as footer %}
ERROR in ./source/twig/index.twig (./node_modules/html-webpack-plugin/lib/loader.js!./source/twig/index.twig)
Module build failed (from ./node_modules/twig-html-loader/index.js):
NonErrorEmittedError: (Emitted value instead of an instance of Error) TwigException: Unable to find template file /app/source/twig/components//////////footer.twig
at runLoaders (/app/node_modules/webpack/lib/NormalModule.js:298:13)
at /app/node_modules/loader-runner/lib/LoaderRunner.js:367:11
at /app/node_modules/loader-runner/lib/LoaderRunner.js:233:18
at Object.context.callback (/app/node_modules/loader-runner/lib/LoaderRunner.js:111:13)
at Object.loader (/app/node_modules/twig-html-loader/index.js:87:10)
Currently we need to use data
option from this loader to add some data it twig template.
But svg-sprite-loader
add sprites in htmlwebpackplugin.files.sprites
and we can't access to this variable in twig file.
Can we add HTMLWebpackPlugin templateParameters
function output as default data
or accessible in data
function?
https://github.com/kisenka/svg-sprite-loader/tree/master/examples/interop-with-html-webpack-plugin
Hi there,
I'm new in this webpack world and I'm practicing using the webpack step-by-step guide.
I'm using twig as a template engine and I wonder if I can inject my js bundles into a twig template.
Well my goal is to render the twig template with javascripts injected in specific place and if it is possible, replace some values given at loader / plugin options.
First I'll expose my webpack.config.js, then my twig templates and finally the rendered result which is not the desired..
Then I'll expose the desired result.
My files right now:
{# src/web/views/base.twig #}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %}{% endblock %}</title>
<meta name="description" content="{{ meta_content }}">
<meta author="{{ author }}" content="{{ author_content }}">
{% block stylesheets %}{% endblock %}
{% block head_scripts %}{% endblock %}
{# WANT TO BE INJECTED HERE print.bundle.js SCRIPT #}
</head>
<body>
{% block body %}{% endblock %}
{# WANT TO BE INJECTED HERE app.bundle.js SCRIPT #}
{% block scripts %}{% endblock %}
</body>
</html>
{# src/web/views/index.twig #}
{% extends "base.twig" %}
{% block title %}{{title}}{% endblock %}
{% block body %}
<h1> Hi world </h1>
{% endblock %}
// webpack.config.js
const path = require('path');
// https://github.com/jantimon/html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
app: './src/web/client/index.js',
print: './src/web/client/print.js'
},
plugins: [
new HtmlWebpackPlugin({
template: './src/web/views/index.twig',
filename: '../../views/index.test.twig'
})
],
mode: 'production',
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'src/web/public/js')
},
// path resolution on imports
// https://webpack.js.org/configuration/resolve
resolve: {
// https://webpack.js.org/configuration/resolve/#resolvealias
alias: {
// key-> alias, value: string -> path to be resolved
}
},
// https://webpack.js.org/configuration/module/
module: {
// can apply rules to use loaders!
// https://webpack.js.org/configuration/module/#modulerules
rules: [
{
test: '/\.twig$/',
use: [
'raw-loader',
{
loader: 'twig-html-loader',
options: {
data: {
title: 'HALLO'
}
}
}
],
}
]
}
}
(src/web/views/base.twig untouched)
{# index.test.twig #}
{% extends "base.twig" %} {% block title %}{{ title }}{% endblock %} {% block body %}<h1>Hi world</h1> {% endblock %}<script src="../public/js/app.bundle.js"></script><script src="../public/js/print.bundle.js"></script>
I event tried to render as index.html, but the result is still the same...
{# src/web/views/base.twig #}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %}{% endblock %}</title>
<meta name="description" content="{{ meta_content }}">
<meta author="{{ author }}" content="{{ author_content }}">
{% block stylesheets %}{% endblock %}
{% block head_scripts %}{% endblock %}
<script src="./js/print.bundle.js"></script>
</head>
<body>
{% block body %}{% endblock %}
<script src="./js/app.bundle.js"></script>
{% block scripts %}{% endblock %}
</body>
</html>
{# index.test.twig #}
{% extends "base.twig" %} {% block title %}HALLO{% endblock %} {% block body %}<h1>Hi world</h1> {% endblock %}
I want to keep the twig template because I have a Node.js server that renders the template. However, I want webpack injects the bundles as it says in this guide: https://webpack.js.org/guides/output-management/#setting-up-htmlwebpackplugin
So I readed many times the docs about this loader and htmlwebpackplugin but without success...
I want to know what I'm doing wrong, and how CAN I ACCOMPLISH MY GOAL.
Thank you so much.
I do not uderstand why we need to use raw-loader.
What part of the job twig-html-loader
and raw-loader
do?
Data option is currently an object.
I would be able to get a json
related to the current twig file as data
So I need a function with current file path as a parameter.
Could it be possible ?
Extend json to support some kind of routing
I guess this might even be a but with twigjs in general. Currently templates that have something like {{ theme_asset('path/to/asset', version = asset_reset) }}
does not work and exits with parsing error
My current options look like this:
options: {
data: {
options: require( path.join(__dirname, '/src/html/_data/options.json') ),
global: require( path.join(__dirname, '/src/html/_data/global.json') ),
}
}
Is there a way to recompile webpack when one of the json files changes? I can watch for file changes with devserver, but that will not rebuild what's in memory already.
In my project with around 100 pages (plus tons of twig imports, macro , etc...) I see the regrasion of RAM memory from 2G to 8G in couple of builds and then webpaack throw "out of memory" error.
I quick looked in to source code of this loader and have some questions, why we every time init Twig then function called? Why not setup Twig once and then use it in next call?
//setup twig here
const Twig= ....
module.exports = function loader(source) {
...
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.