html-webpack-plugin output html , interior body empty - node.js

use html-webpack-plugin output html page , but in output page lost body inner html element , like <div id="app"></div> , here is my input output and webpack.config file :
input
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
<link rel="icon" href="static/pic/logo.png" type="image/x-icon">
<link rel="stylesheet" href="static/weui/weui.min.css">
<link rel="stylesheet" href="static/index.css">
<title>APP</title>
</head>
<body>
<div id="app"></div>
<script src="./dist/vendor.js"></script>
<script src="./dist/app.js"></script>
</body>
</html>
output
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPA</title>
<link href="/dist/style.df241090c6a9e0a6bf26.css" rel="stylesheet"></head>
<body>
<script type="text/javascript" src="/dist/vendor.df241090c6a9e0a6bf26.js"></script><script type="text/javascript" src="/dist/app.df241090c6a9e0a6bf26.js"></script></body>
</html>
part webpack.config.js
const htmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
new htmlWebpackPlugin({
title:'SPA',
filename: 'assets/index.html'
})
],

The filename option is simply used as the output file, it won't read and modify the existing file, if one exists. Because if it did that, every new build would just append to it, unless you cleaned it manually. To use your input as the base, you need to use it as a template.
new htmlWebpackPlugin({
title:'SPA',
filename: 'assets/index.html',
template: 'path/to/template/index.html'
})
The template should not be the same as the output filename, otherwise it gets overwritten. See also Writing Your Own Templates. The template can be a regular HTML file and it will inject the necessary assets.

Related

stylesheet does not work in handlebar template

I am using handlebars template in express and node. But seems like it cannot apply style in my template
here is my directory:
my template
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RYZE Report</title>
<link rel="stylesheet" href="./css/style.css" >
</head>
<body>
<h1>Hello hi</h1>
</body>
</html>
and in my app.js, I have this line
app.use(express.static(__dirname + '/public'))
Thank you
I have looked at the code and I made a couple of improvements to make this work, instead of compiling the document without any inputs, I have made a css input as the following in the template.hbs:
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
{{css}}
</style>
<title>Hello, world!</title>
I have also edited the app.js to read the css along with the html and embed the css into it like so: app.js:
const template = fs.readFileSync('template.hbs', 'utf8');
const css = fs.readFileSync('./public/css/style.css', 'utf-8');
const DOC = Handlebars.compile(template);
and used the DOC as following:
DOC({css})
this will inline the css inside of the hbs file, I hope this answers your question

Chartist not defined error in Node / express app

I am trying to use Chartist in a Node app using ejs to render my HTML . I am using the Chartist CDN and have included the necessary scripts etc in my header.ejs and set up my data model in the main.ejs file I want to render. However I keep getting "Chartist not defined error". I have tried moving the script tag into my footer, as per another answer on SO, but that didn't work either. My header.ejs and main.ejs are as follows. Is there something I am missing?
header.ejs:
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="stylesheets/styles.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/chartist.js/latest/chartist.min.css">
<script src="https://cdn.jsdelivr.net/chartist.js/latest/chartist.min.js"></script>
</head>
<body>
And main.ejs
<%- include('partials/header') %>
<h1>GRAPH</h1>
<div class="ct-chart ct-perfect-fourth"></div>
<% let data = {
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
series: [
[5, 2, 4, 2, 0]
]
};
%>
<% new Chartist.Line('.ct-chart', data); %>
<%- include('partials/footer') %>

Adding CSS File to ejs tempelate using variable from server side

I am trying to add css file dynamically in ejs tempelate.
I know how to include ejs file but not getting how to add css file dynamically.
Code :-
Index.js
router.get('/', function(req, res, next) {
res.render('template', { title: 'abc',page:'index',cssa:'home'});
});
template.ejs
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="/stylesheets/style.css">
<!-- Here I want to add home.css file -->
</head>
<body>
<!-- including my ejs file -->
<%- include(page) %>
</body>
</html>
I tried :
<link rel="stylesheet" type="text/css" href="/stylesheets/\<%= cssa %>\" >
<% include %><%= cssa %><% .css %>
Goal:
to pass the server side received variable(cssa) in stylesheet source.
Don't need to concat the css path and variable, you can also do it as follows:
<link rel='stylesheet' href='/stylesheets/<%= yourVariableName %>.css' />
Method to include :
<% var css_link = '/stylesheets/' + cssa + '.css'; %>
<link rel="stylesheet" type="text/css" href="<%= css_link %>" >
Credit goes to #SpiRT
Alternatively :
<link rel="stylesheet" type="text/css" href="/stylesheets/<%=cssa%>.css">
I've found it most convenient to inject custom css scripts through an array which can then be processed in the ejs template.
This method would allow you to render any amount of CSS files that are additionally required (example, you have a site that uses 1 standard css across all pages but have 1 or 2 page specific ones which can then be included in the model passed through the ejs renderer to that specific page/route).
In the example it's a given that the css files are in the same folder, however that can be changed to each one's liking:
router side:
router.get( ... {
model = {};
model.Stylesheets = [];
model.Stylesheets.push("stylefile");
res.render("view",{model:model});
});
with the custom stylesheets being pushed though to the view, then the ejs files can be something like:
<%
var customStylesheets = "";
model.Stylesheets.forEach(function(style){
customStylesheets+='<link type="text/css" rel="stylesheet" href="css/'+style+'.css">';
})
%>
<!DOCTYPE html>
<html>
<head>
<title><%= model.title %></title>
<link type="text/css" rel="stylesheet" href="css/standard.css">
<%- customStylesheets %>
...
</head>

EJS/Node/Express - Having a header partial, how to change title for each page?

I recently took a course on back-end web developing.
As the title says, I don't get how can I use a header partial for the whole website but have different titles for each page. (because is included in the tag)
Is there any trick?
1st) In your Express route:
app.get("/", function(req, res){
res.locals.title = "Abel's Home Page"; // THIS LINE IS KEY
res.render("home.ejs");
});
2nd) In your views/home.ejs file:
<% include partials/header.ejs %>
3rd) In your views/partials/header.ejs file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title><%= title %></title> <!-- THIS LINE IS KEY -->
<link rel="stylesheet" href="../style.css">
<link rel="shortcut icon" href="../logo_sm.png" type="image/x-icon">
</head>
<body>
Each page that includes the partial is free to pass data to said partial through parameters. See here for an example.

Thymeleaf layout dialect and th:replace in head causes title to be blank

I'm following this tutorial: http://www.thymeleaf.org/doc/layouts.html (got to Thymeleaf Layout Dialect section).
In there you can find an example:
<!DOCTYPE html>
<html>
<head>
<!--/* Each token will be replaced by their respective titles in the resulting page. */-->
<title layout:title-pattern="$DECORATOR_TITLE - $CONTENT_TITLE">Task List</title>
...
</head>
<body>
<!--/* Standard layout can be mixed with Layout Dialect */-->
<div th:replace="fragments/header :: header">
...
</div>
<div class="container">
<div layout:fragment="content">
...
</div>
<div th:replace="fragments/footer :: footer">© 2014 The Static Templates</div>
</div>
</body>
</html>
Footer and header are replaced by th:replace tag in above example, while <head> has <title> tag in layout file.
Basically, I want to replace whole <head> tag with th:replace.
Therefore, I have:
My layout file:
<!DOCTYPE html>
<html>
<head th:replace="/html/components/head :: head">
</head>
<body>
<div layout:fragment="content">
</div>
...
<div th:replace="/html/components/footer :: footer" />
</body>
<html>
My content file:
<!DOCTYPE html>
<html layout:decorator="/html/layouts/layout">
<head>
<title>My content title</title>
</head>
<body>
<div layout:fragment="content">
...
</div>
</body>
</html>
And finally my /html/components/head.htm file:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head th:fragment="head">
<meta charset="utf-8" />
<title layout:title-pattern="$CONTENT_TITLE">Layout Title should be replaced by Content Title!</title>
...
</head>
<body>
</body>
</html>
Content is alright. Footer and head are included (replaced) from files as expected but page title is blank!
I get:
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title></title>
...
What's wrong?
Finally, I've found a way to achieve what I wanted.
In layout file <title> tag must stay. All other tags I grouped with <object> tag and annotated it as follows:
<head>
<title layout:title-pattern="$CONTENT_TITLE">Layout Title will be replaced by Page Title!</title>
<object th:include="/html/components/head :: head" th:remove="tag" />
</head>
In my html/components/head.htm file I had to remove <title> tag so it won't be duplicated after include.
<head th:fragment="head">
<meta charset="utf-8" />
<!-- NO TITLE TAG HERE -->
...
</head>
This way head fragment is included in <object> tag and thanks to th:remove="tag" <object> tag gets removed and my final HTML output is:
<head>
<title>My content title</title>
<meta charset="utf-8" />
<!-- NO TITLE TAG HERE -->
...
</head>
Obviously, I removed NO TITLE TAG HERE message too, once I got it working.
I think I found a slightly less verbose way to for using th:replace and th:fragment together, e.g. to include common <head> metadata and static resource includes in your pages.
Put the th:remove="tag" in the fragment definition, so you don't have to repeat the th:remove="tag" everytime including it.
fragment_head.html
<thymeleaf xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
th:fragment="head" th:remove="tag">
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" th:href="#{/css/vendor/bootstrap.min.css}"/>
</thymeleaf>
mypage.html
<head>
<thymeleaf th:replace="fragment_head :: head" />
</head>
You can replace whole head tag.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head lang="pl" th:replace="fragments/head :: head">
</head>
<body>
...
</body>
</html>
resources/templates/fragments/head.html:
<head lang="pl">
<title>Title</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link href="http://cdn.jsdelivr.net/webjars/bootstrap/3.3.5/css/bootstrap.min.css"
th:href="#{/webjars/bootstrap/3.3.5/css/bootstrap.min.css}"
rel="stylesheet" media="screen" />
<script src="http://cdn.jsdelivr.net/webjars/jquery/2.1.4/jquery.min.js"
th:src="#{/webjars/jquery/2.1.4/jquery.min.js}"></script>
<link href="../static/css/mycss.css"
th:href="#{css/mycss.css}" rel="stylesheet" media="screen"/>
</head>

Resources