How do I import static assets in a static html page with webpack? - html

Problem Context
I have webpack working for compiling my typescript into javascript. Automatic reloading works when I change my typescript code. However, webpack is not watching my static html file.
.
├── dist
│ ├── index.html
│ └── style.css
├── src
│ └── index.ts
└── webpack.config.js
The problem is I need to make several changes in my index.html and webpack does not automatically detect those changes. And, if I refresh the html page, it seems to break webpack's webpack-dev-server.
Expected Output
I want everything to be in the src folder and when I run webpack I have a fully working static site in my dist folder. That is:
. .
├── dist ├── dist
├── src │ ├── index.html
│ ├── index.html │ ├── bundle.js
│ ├── index.ts npx webpack -> │ └── style.css
│ └── style.css ├── src
└── webpack.config.js │ ├── index.html
│ ├── index.ts
│ └── style.css
└── webpack.config.js
The files in the dist folder might have hashed filenames. I'm not worrying about that step for now though. I expect that webpack will go through my files and make sure they link to the correct resources. So if webpack were to give style.css a hashed name, the href in index.html would be updated.
Current Output
My current solution outputs both index.html and bundle.js, but I cannot get it to copy style.css into the dist folder. My current webpack.config.js looks like the this:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: './src/index.ts',
devtool: 'inline-source-map',
mode: 'development',
devServer: {
contentBase: './dist'
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.html$/,
use: [
{ loader: 'file-loader?name=[name].[ext]' },
{ loader: 'extract-loader' },
{ loader: 'html-loader' }
]
}
]
},
plugins: [
new CleanWebpackPlugin()
],
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
And my index.html looks like this:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>stuff</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<script src="./bundle.js" charset="utf-8"></script>
</body>
</html>
My index.ts contains:
import './index.html';
What I Tried
At first I tried just adding an import for my css into my index.ts:
import './style.css';
But this did not work. Next I looked at the html-loader documentation, and it seemed to hint at what I'm looking for:
However, I've read that inlining loaders like that is deprecated, and looking through the source there doesn't seem to be any configuration option for interpolation. I tried to do it as described in the documentation anyways, but it either simply does not work, or gives me some error message about require not found (I can't seem to reproduce that error though). My index.html contained:
<link rel="stylesheet" href="${require(`style.css`)">
and index.ts contained:
require("html-loader?interpolate=require!./index.html");
How do I get webpack to move my style.css to the dist folder?
I have the hunch I'm misunderstanding how webpack is supposed to be used. When I have something working can I post my webpack config on the code review stack exchange to get help creating a more idiomatic webpack config?

When creating a CSS file, try using MiniCssExtractPlugin to write CSS to a new file
import './style.css'; - this should work, but write CSS inline in the head of html.
{ use: [MiniCssExtractPlugin.loader, 'css-loader'] }
For file name pattern: [name].[contenthash].bundle.js
Use HtmlWebpackPlugin for auto updating [contenthash]
const plugins = () => {
const result = [
new HtmlWebpackPlugin({
template: "./index.html", // this file will be used as html and all css/js will be automaticly included
})
]}

Related

Gulpfile relative path to root

I want to approach my deploy folder from my gulpfile, I placed the gulpfile in the source folder so that it stays tidy. My current folder structure:
deploy
├── js
├── css
├── img
└── index.php
source
├── node_modules
├── base
├── structure
└── gulpfile.js
Structure above is only a part of the full tree
Part of gulpfile.js:
var path = {
js: {
src: [
'./source/_base/**/js/*.js',
'./source/_structure/**/js/*.js'
],
deploy: [
'../deploy/js/'
]
},
// more below this line
The gulp task:
gulp.task('process-js', function(){
gulp.src(path.js.src)
.pipe(plumber())
.pipe(jshint())
.pipe(jshint.reporter(stylish))
.pipe(concat('main.min.js'))
.pipe(uglify())
.pipe(plumber.stop())
.pipe(gulp.dest(path.js.deploy));
});
When I execute my gulp task (which uses this deploy path) I get an error:
:Error: Invalid output folder at Gulp.dest
Question:
How can I use the gulpfile relative path to place files in the parent of the root folder.
I've found the solution, it is - of course - not possible to parse an array as a destination.

How to export (dest) in multiple folder [duplicate]

I am trying to copy files from one folder to another folder using Gulp:
gulp.task('move-css',function(){
return gulp.src([
'./source/css/one.css',
'./source/other/css/two.css'
]).pipe(gulp.dest('./public/assets/css/'));
});
The above code is copying one.css & two.css to the public/assets/css folder.
And if I use gulp.src('./source/css/*.css') it will copy all CSS files to the public/assets/css folder which is not what I want.
How do I select multiple files and keep the folder structure?
To achieve this please specify base.
¶ base - Specify the folder relative to the cwd. Default is where the glob begins. This is used to determine the file names when saving in .dest()
In your case it would be:
gulp.task('move-css',function(){
return gulp.src([
'./source/css/one.css',
'./source/other/css/two.css'
], {base: './source/'})
.pipe(gulp.dest('./public/assets/'));
});
Folder structure:
.
├── gulpfile.js
├── source
│ ├── css
│ └── other
│ └── css
└── public
└── assets
I use gulp-flatten and use this configuration:
var gulp = require('gulp'),
gulpFlatten = require('gulp-flatten');
var routeSources = {
dist: './public/',
app: './app/',
html_views: {
path: 'app/views/**/*.*',
dist: 'public/views/'
}
};
gulp.task('copy-html-views', task_Copy_html_views);
function task_Copy_html_views() {
return gulp.src([routeSources.html_views.path])
.pipe(gulpFlatten({ includeParents: 1 }))
.pipe(gulp.dest(routeSources.html_views.dist));
}
And there you can see the documentation about gulp-flatten: Link
gulp.task('move-css',function(){
return gulp
.src([ 'source/**'], { base: './' })
.pipe(gulp.dest('./public/assets/css/'));
});
Your own code didn't include the entire dir tree of source 'source/**' and the base {base:'./'} when calling to gulp.src which caused the function to fail.
The other parts where fine.
gulp.task('move-css',function(){
return gulp.src([
'./source/css/one.css',
'./source/other/css/two.css'
]).pipe(gulp.dest('./public/assets/css/'));
});

Gulp: preserving folder structure on destination for individual files

Let’s say we have the following folder structure:
rootDirectory
│
│
├──a
│ ├──a.txt
│
├──b
│ ├──a
│ ├──a.txt
│
├──c.txt
also, let’s say we need to write a Gulp task that will take a.txt in the a folder, and c.txt; perform some manipulations on them, and then pipe them into the build directory. What I want is for the files copied in the build folder to keep their directory structure in the build folder (and I do not want files that were not supposed to be processed by the task to get in the build folder), like so:
rootDirectory
│
│
├──a
│ ├──a.txt
│
├──b
│ ├──a
│ ├──a.txt
│
├──c.txt
│
├──build
│
├──a
│ ├──a.txt
│
├──c.txt
Now, here is what puzzles me. If I specify paths to specific files:
gulp.task('foo', function(){
var files = [
path.join(__dirname, 'c.txt'),
path.join(__dirname, 'a/a.txt')
];
gulp.src(files)
.pipe(gulp.dest(path.join(__dirname, build));
});
then I will flatten the folder structure in the build directory.
If, however, I use the globbing pattern:
gulp.task('foo', function(){
var files = [
path.join(__dirname, '**/c.txt'),
path.join(__dirname, '**/a/a.txt')
];
gulp.src(files)
.pipe(gulp.dest(path.join(__dirname, build));
});
then the folder structure is preserved, but this globbing pattern will also target b/a.txt, which I do not want.
Is there a way to achieve what I describe in Gulp? Basically, telling Gulp: "Here, take this file, do whatever you need with this, and put it in another path keeping the folder structure starting from this root path"? Apart from specifically negating globbing paths that I do not want to match?
In order to preserve hierarchy you should pass {base: "."} parameter to the gulp.src. Something like this:
gulp.task('foo', function(){
var files = [
path.join(__dirname, 'c.txt'),
path.join(__dirname, 'a/a.txt')
];
gulp.src(files, {base: '.'})
.pipe(gulp.dest(path.join(__dirname, build));
});

Why does node.js app CSS load in my IDE but not on a localhost?

I am making a nodejs application using LightTable, and the css seems to be loading fine when I indicate a relative path to the file in my <link href=""> tag. When I run node index.js, however, the server starts up and the page loads fine, but I get a console error and my own 404 saying the CSS file could not be found at the path specified. I tried using Heroku's Foreman Start as well, but no dice. Here is the html:
<!DOCTYPE html>
<html>
<head>
<title>
Home
</title>
<link href="../../styles/master.css" rel="stylesheet" type="text/css" />
</head>
...
Here is my directory tree structure:
.
├── Procfile
├── README.md
├── index.js
├── package.json
├── resources
│   └── images
│   └── tokyo.jpg
├── styles
│   └── master.css
└── views
├── get
│   ├── home.html
│   └── posts.html
└── post
└── new.html
EDIT: after finding the answer to the question, the below information became relevant. I have commented out the new code that makes the CSS and background image load as desired.
Here is my routing and server code. I am not using Express, on purpose:
// routes
var homeREGEX = new RegExp('^/?$');
var newREGEX = new RegExp('^/posts/new/?$');
var postsREGEX = new RegExp('^/posts/?$');
// var cssREGEX = new RegExp('^/styles/master.css/?$'); <--| static resources also
// var tokyoREGEX = new RegExp('^/resources/images/tokyo.jpg/?$'); <--| need routes.
// server
var server = http.createServer(function(request, response){
var pathname = url.parse(request.url).pathname;
if (homeREGEX.test(pathname)) {
renderHome(request, response);
} else if (newREGEX.test(pathname)) {
renderPostForm(request, response);
} else if (postsREGEX.test(pathname)) {
addNewPost(request, response);
// } else if (cssREGEX.test(pathname)) { <--| and they need to get
// sendCSS(request, response); <--| served individually as
// } else if (tokyoREGEX.test(pathname)) { <--| they are requested
// sendTokyo(request, response);
} else {
error404(request, response);
}
});
What's the url you use in your browser when viewing the page ? My guess is that is does not contains the views/get part, which means that you don't need the ..\.. in your link href attributes.
Also, make sure your are actually serving these static files (it seems you're not). If you're using express (with nodejs ) for example, you'll need something like this :
app.use(express.static('resources'));
app.use(express.static('style'));
See express.static documentation.
Maybe you can try to put the exact path instead of ../../
<link href="/Procfile/styles/master.css" rel="stylesheet" type="text/css" />

Can you remove a folder structure when copying files in gulp?

If I use :
gulp.src(['app/client/**/*.html'])
.pipe(gulp.dest('dist'));
The folder structure in which my .html files were in, is maintained in the dist folder, but I would like to remove the folder structure completely and just a flat hierarchy in my dist folder.
You could use gulp-rename to accomplish this:
var rename = require('gulp-rename');
gulp.src('app/client/**/*.html')
.pipe(rename({dirname: ''}))
.pipe(gulp.dest('dist'));
You can use gulp-flatten
https://www.npmjs.com/package/gulp-flatten
app
├── logo
│ └── logo.styl
└── sidebar
└── sidebar.styl
var flatten = require('gulp-flatten');
gulp.src('app/**/*.styl')
.pipe(flatten())
.pipe(gulp.dest('dist/'));
dist
├── logo.styl
└── sidebar.styl