I'm working on an HTML 5 app that I'm building with Grunt. I am trying to use the grunt-preprocess task on my HTML. In attempt to just see if it works, I have the preprocess task setup as follows:
module.exports = function(config) {
return {
dev: {
cwd: 'build/temp',
src: [
'**/*.css',
'**/*.js',
'index.html',
'app/**/*.html'
],
options: {
inline : true,
context: {
ENV: 'dev'
}
}
}
};
};
I have a basic index.html file that looks like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title>Test</title>
</head>
<body>
<!-- #exclude -->
<header>You're on dev!</header>
<!-- #endexclude -->
Welcome
</body>
</html>
I've added the exclude directive just to see if its running through the preprocessor. I know that grunt is running the preprocess task. I'm basing this on the fact that when I run grunt --verbose, I see the following at the end:
Running "preprocess:dev" (preprocess) task
Verifying property preprocess.dev exists in config...OK
Files: css/animations.css, css/app.css, css/application.css,...
Verifying property preprocess exists in config...OK
Options: inline, context={"ENV":"dev"}
Reading css/animations.css...ERROR
Warning: Unable to read "css/animations.css" file (Error code: ENOENT). Use --force to continue.
I can't make sense of this error. The error says css/animations.css can't be found. Yet, it shows it in the Files list previously. I've also confirmed its on the file system.
Can somebody please tell me what I'm doing wrong?
You need to set expand: true when using cwd.
See http://gruntjs.com/configuring-tasks#building-the-files-object-dynamically for more info
Your task would become:
dev: {
expand: true,
cwd: 'build/temp',
src: [
'**/*.css',
'**/*.js',
'index.html',
'app/**/*.html'
],
options: {
inline : true,
context: {
ENV: 'dev'
}
}
}
Related
I added a new meta tag to next/head
import Head from "next/head";
export default function Home() {
return (
<>
<Head>
<title>Hello world!</title>
<meta
http-equiv="Content-Security-Policy"
content="upgrade-insecure-requests"
/>
</Head>
...
but this meta tag is missing from inside the <head> tags when the app is launched with next dev or next start.
How can we get Next.js to include them in the <head>?
You need to add security headers via the next.js config.
See: https://nextjs.org/docs/advanced-features/security-headers
// next.config.js
module.exports = {
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'Content-Security-Policy',
value: "upgrade-insecure-requests"
}
],
},
]
},
}
You will see your working settings in the dev console: Network > Headers > Response Headers
If you do not want to add a lot of relevant headers manually, you might be interested in checking out next-safe.
I am running Angular 8 with the Custom Webpack builder.
"builder": "#angular-builders/custom-webpack:browser",
I have a reference to the ngx-datatable, and I reference the css as follows:
#import '~#swimlane/ngx-datatable/release/assets/icons.css';
That referenced css file has a font-face like so:
#font-face {
font-family: "data-table";
src:url("fonts/data-table.eot");
src:url("fonts/data-table.eot?#iefix") format("embedded-opentype"),
url("fonts/data-table.woff") format("woff"),
url("fonts/data-table.ttf") format("truetype"),
url("fonts/data-table.svg#data-table") format("svg");
font-weight: normal;
font-style: normal;
What I want to do is inline the data-table font file into my webpack'd build. My understanding is that, after installing the base64-inline-loader, I should be able to have a custom webpack config that looks like this:
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
use: 'base64-inline-loader'
}
]
}
};
However, after running the build, nothing gets inlined, and I can see the browser is making a request to
http://localhost:4200/data-table.woff
It's not clear to me how to fix this. My understanding is that for files like .png, .woff, .eot, etc, the default Angular webpack configuration will use the file-loader, which will spit out a hashed version of the file in the dist directory. However even after adding the base64-inline-loader, I am still seeing the files get copied and hashed, instead of inlined.
Edit
I believe my problem is related to Angular 7, svg and sass how to set relative path, but I'm still not sure how to fix it.
Could it be that your Webpack.config.js might need some tweaking?
I prefer to keep the command line clean (here: webpack --config Webpack.config.js) and put everything into the configuration file. Assuming that you are using a newer version of Webpack, I suggest a configuration file similar to this this
var path = require('path'); // this is essential for path.resolve()
module.exports = {
mode: 'development',
entry: './yourEntryPage.js',
output: {
path: path.resolve(__dirname, 'dist'), // specifies the output
filename: 'bundle.js'
},
devtool: "source-map", // for debugging webpack's output.
module: {
rules: [
{ test: /\.jsx$|\.es6$|\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['react'],
}
},
exclude: /node_modules/
},
{ test: /\.(png|jpg|gif)$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/'
}
}
},
{ test: /\.(ttf|eot|woff(2)?)$/, // modified regex matching files with font extension
use: 'base64-inline-loader'
}
]
}
};
You cannot directly use this configuration file, but I hope my suggestion gives you an idea on what a not-so-minimal configuration for Webpack could look like. The Webpack.config.js you suggested might not only have a path problem, but might also miss to specify the hierarchy of the different loaders. It could well be that your inline-loader case-statement is never reached.
Note: I do not know #angular-builders/custom-webpack:browser, but I hope it helps anyhow if that package does not interfere too much with Webpack.config.js. My experience tells me that in 95% of the cases the cuplrit is a webpack configuration issue. A --verbose, --progress or -d might become handy, see Webpack's CLI documentation.
The webpack will inline the font into your output .js file (or .woff file) but will not serve it. This means that you have to manually add this font in your static assets in angular.json:
"assets": [
"src/assets",
{
"glob": "**/*",
"input": "node_modules/swimlane_or_whatever/assets/",
"output": "my-assets"
},
The code above means that after you run the development server, the resource /my-assets/fonts.woff will be resolved and passed to the client.
Which loader/plugin should I use to move multiple html files from one folder (src) to another (dist) which only imports files that obey certain rules in this example I need to import multiple html files, so the regex would be:
/.html$/
I know that I can move html using html-webpack-plugin but I don't want to create object instance for every page I want to move. I also don't want to make multiple imports in my app.js (entry point for webpack).
So i tried with copy-webpack-plugin but this one moves everything from src to dist. Is it possible to filter with my regex pattern or do you know other way that works to do this?
new CopyWebpackPlugin([{
from: './src',
to: path.resolve(__dirname, "dist")
}],
I gues that I could use system
mkdir dist && cp ./src/*.html ./dist
And simply run this in my package.json in the script before running webpack -d
but this is not the "polite" way of doing this. I'm sure that webpack can do that easily..
Ps. Also, it would be nice to minimize those files, if possible.
Moving all files in batch
So for now it works like this. To not have to include every single file from the src folder in to my app.js (which is my entry point for webpack) I required all files using require.context()
Because my app.js is also in my src folder I use relative path to require all other file:
// requires all files in current directory and sub directories
require.context("./", true, /^\.\/.*\..*/);
Or if you want to import files with certain extension sue this instead:
// requires all html files in current directory and sub directories
require.context("./", true, /^\.\/.*\.html/);
So now everything is imported and I don't have to require files manually. The only thing I have to do is set entry to app.js using path.resolve.
I now can use test property to get what I want from within in webpack.config.js module rules.
...
module: {
rules: [
{
test: /\.(html)$/,
use:
[
{
loader: 'file-loader',
options: {
name: '[path][name].[ext]',
context: './src',
outputPath: '/',
publicPath: '/'
}
},
...
This works fine my files are moved (but not minified). Perhaps someone can take this a little bit further and the answer will be completed.
Below i place full file for reference only
webpack.config.js
// imports node plugin which allows us to save data to a file for example css external files
var ExtractTextPlugin = require("extract-text-webpack-plugin");
// cleans defined folders before webpack will build new files now we can remove package.json commands "rm -rf ./dist && ..."
var CleanWebpackPlugin = require("clean-webpack-plugin");
// copies to memory html from template file and injects css and javascript as well as img src to newly generated html file.
var HtmlWebpackPlugin = require("html-webpack-plugin");
// to include jquery we need to import 'jquery' in app.js but also we need to make connection between bundle.js jquery script
var Webpack = require('webpack');
// includes node path resover that is need for webpack-dev-server to run properly
var path = require('path');
// webpack configuration
module.exports = {
entry: [
path.resolve(__dirname, "src/app.js"),
],
output: {
path: path.resolve(__dirname, 'dist'), // defins the main utput directory
filename: 'js/bundle.js',
},
devServer: {
contentBase: path.join(__dirname, "dist"),
compress: true,
port: 8080,
},
module: {
rules: [
{
test: /\.(html)$/,
use:
[
{
loader: 'file-loader',
options: {
name: '[path][name].[ext]',
context: './src',
outputPath: '/',
publicPath: '/'
}
},
]
},
{
test: /\.(jpg|png|gif)$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'img/',
publicPath: '/' // this path relates to reference path from the index.html file that imports out bundle.js file
}
}
},
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
]
},
{
test: /\.sass$/,
include: [
path.resolve(__dirname, "src/sass")
],
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
//resolve-url-loader may be chained before sass-loader if necessary
use: [
{
loader: 'css-loader',
options: {
minimize: false,
sourceMap: true,
}
},
'sass-loader'
]
})
},
]
},
plugins: [
// mapping jQuery variable to our node module dependency (remember to import 'jquery' in app.js)
// below we make jquery available as both the $ and jQuery variable
new Webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
}),
// use extract plugin to build an external file loded by sass-loader > complied to css > movig to bundle.css
new ExtractTextPlugin({
filename: 'css/bundle.css'
}),
// remove all files from this folder before generating new files
// new CleanWebpackPlugin(['dist']),
],
}
You should be able to use copy-webpack-plugin's support for globs to achieve what you want.
new CopyWebpackPlugin([
{
from: './src/*.html',
to: path.resolve(__dirname, 'dist')
}
])
The globs accept minimatch options too.
EDIT:
In addition, if you're copying just HTML (and want to minify them), you might want to take a look at html-webpack-plugin. The minify option allows you to minify those HTML files.
I want to read a CSV file with headers to populate a datatable widget following this documentation. However, I get an uncaught exception: [object XMLHttpRequest] error when I execute the following code:
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" href="http://cdn.webix.com/edge/webix.css" type="text/css">
<script src="http://cdn.webix.com/edge/webix_debug.js" type="text/javascript"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="//cdn.opencpu.org/opencpu-0.4.js"></script>
</head>
<body>
<script type="text/javascript" charset="utf-8">
webix.ui({
rows:[
{ view:"template",
type:"header", template:"Read in a CSV" },
{ view:"datatable",
columns:[
{ id:"#x#", header:"x" },
{ id:"#y#", header:"y" },
{ id:"#z#", header:"z" }],
datatype:"csv",
autoheight:true,
autowidth:true,
url:"data/basic.csv"
}
]
});
</script>
</body>
</html>
In addition, I see the following notifications appear in the upper right-hand corner of the browser.
The error details from the log are:
"XHTTP:" XMLHttpRequest { onreadystatechange: webix.ajax.prototype._send/x.onreadystatechange(), readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, status: 0, statusText: "", responseType: "", response: "x,y,z
1,1,23.3
1,2,15.8
2,1,88.3
2,2,83.5
", responseText: "x,y,z
1,1,23.3
1,2,15.8
2,1,88.3
2,2,83.5
" } webix_debug.js:3240
uncaught exception: [object XMLHttpRequest]
It appears to read the CSV file just fine. Why doesn't it display? I have to admit, I find the documentation confusing as it doesn't mention CSV headers at all.
Are you run the sample page by the http (with some kind of web server), or open it directly from a file system?
Due to security limitations, ajax request may not work for pages that was loaded directly from a file system.
Also, to map data correctly, you need to use datatable columns config like next
columns:[
{ id:"data0", header:"x" },
{ id:"data1", header:"y" },
{ id:"data2", header:"z" }],
DataTable will not recognize header and map CSV data to abstract data0..dataN properties.
My setup consists of a lot of .js files being used in my base.html template and the same list being repeated in my Gruntfile.js when concatenating all the files for production.
How can I have the list of files in a single JSON (or whatever other format) and be able to pass it to both Django and Grunt?
Here's a simplified example:
base.html:
<html lang="en">
<head>
<title></title>
</head>
<body>
<script src="static/some.js"></script>
<!-- a lot more js files go here -->
</body>
</html>
Gruntfile.js:
uglify: {
options:{},
build: {
options:{
report: 'min'
},
files: {
'static/some.min.js': [
'static/some.js',
// lots of other js files go here
]
}
}
I know that Grunt can load JSON files through grunt.file.readJSON('files.json') or require('files.json') but how can I do the same in Django templates?
In case anybody is interested, here's what I went for:
sample.json:
{
"files": [
"file1.js",
"file2.js"
]
}
Grunt task:
module.exports = function(grunt) {
var generalJS = prepare(grunt.file.readJSON('sample.json'));
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
options:{},
build: {
options:{},
files: {
'sample.min.js': generalJS.files
}
}
}
});
grunt.registerTask('build', ['uglify']);
}
Django template tag:
#register.simple_tag
def render_js_files(file_location):
result = ""
static_base_path = settings.STATIC_DIR
json_js_files_path = os.path.join(static_base_path, file_location)
json_data = open(json_js_files_path)
data = json.load(json_data)
files_dirs = data['files']
json_data.close()
src_template = "<script src='%s'></script>\n"
for js_file_path in files_dirs:
result += src_template % urljoin(PrefixNode.handle_simple("STATIC_URL"), js_file_path)
return result
Usage in base.html:
{% render_js_files 'sample.json' %}