I have the following webpack.config.js file:
'use strict';
let path = require('path');
let webpack = require('webpack');
let HtmlWebpackPlugin = require('html-webpack-plugin');
let ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: [
'./index.js'
],
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/'
},
devtool: 'inline-source-map',
watch: true,
module: {
rules: [
{
test: /\.jsx?$/,
use: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: [ 'style-loader', 'css-loader?modules', ],
publicPath: '/dist'
})
},
{
test: /\.ejs$/,
use: 'ejs-compiled-loader'
}
],
},
plugins: [
new ExtractTextPlugin({
filename: 'styles.css'
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(),
new HtmlWebpackPlugin({
minify: {
collapseWhitespace: true
},
hash: true,
template: 'ejs-render-loader!./views/index.ejs'
}),
]
};
When trying to load an ejs file that contains <% somefile %> the file cannot be found.. this is the error I receive:
Child html-webpack-plugin for "index.html":
Asset Size Chunks Chunk Names
index.html 26.2 kB 0
chunk {0} index.html 554 bytes [entry]
[./node_modules/ejs-render-loader/index.js!./views/index.ejs] ./~/ejs-render-loader!./views/index.ejs 554 bytes {0} [built] [failed] [1 error]
ERROR in ./~/ejs-render-loader!./views/index.ejs
Module build failed: Error: ENOENT: no such file or directory, open 'head.ejs'
at Object.fs.openSync (fs.js:584:18)
at fs.readFileSync (fs.js:491:33)
at Object.exports.parse (/var/www/rio-olympics-3/monitor/node_modules/ejs-compiled-loader/node_modules/ejs/lib/ejs.js:168:19)
at Object.exports.compile (/var/www/rio-olympics-3/monitor/node_modules/ejs-compiled-loader/node_modules/ejs/lib/ejs.js:245:15)
at Object.module.exports (/var/www/rio-olympics-3/monitor/node_modules/ejs-compiled-loader/index.js:7:22)
webpack: Failed to compile.
I have tried many file path formats, and none of them worked, here is my ejs file with my head.ejs in the same folder:
<!DOCTYPE html>
<html lang="en">
<% include head %>
<body>
<div id="navbar-app"></div>
<p> Welcome, more coming soon! </p>
</body>
<!-- insert component scripts below here -->
<script src="dist/js/NavBarMain.js"></script>
</html>
You have two different loaders configured for the index.ejs, which results in a clash.
A general rule for all .ejs:
{
test: /\.ejs$/,
use: 'ejs-compiled-loader'
}
An inline rule for the template in html-webpack-plugin:
template: 'ejs-render-loader!./views/index.ejs'
If you only want to use the inline loader you can add a leading !, so webpack won't apply other loaders:
template: '!ejs-render-loader!./views/index.ejs'
The above fixes your problem, but it is a little questionable why you have two different ejs loaders. To be honest I'm not fully aware of the differences in the loaders since both point to the same GitHub repository, although it seems to me like ejs-render-loader is just an earlier version. They actually handle the includes differently, that's why you get the error.
From the example in Usage of ejs-compiled-loader:
// Child Templates
// path is relative to where webpack is being run
<%- include templates/child -%>
That means if you want to use the ejs-compiled-loader for all .ejs you need to change the include to:
<% include views/head %>
And you can get rid of the inline loader in the html-webpack-plugin:
template: './views/index.ejs'
It's up to you whether you want to change this, I would just try to avoid loader conflicts and I don't think ejs-render-loader will be updated anymore.
In fact there is a v2.2.0 of ejs-compiled-loader which went back to the other include behaviour, relative to the current file, which is definitively more intuitive. You can install it with:
npm install --save-dev ejs-compiled-loader#2.2.0
Related
I am new to webpack. I am learning react and building environment for it using webpack.
I have webpack-config.js
var path = require('path');
module.exports = {
mode: 'production',
entry: './script.js',
output:
{
path: path.resolve(__dirname, 'src'),
filename: 'transpiled.js'
},
module:
{
loaders: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
query:
{
presets: ['es2015','react']
}
}
]
}
}
and script.js
import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(
<h1>Hello world</h1>
document.getElementByIdName('first')
);
and index.html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div class="first"></div>
<script src="transpiled.js"></script>
</body>
</html>
in Pakage.json file I have written
"scripts": {
"it": "webpack-dev-server --hot"
},
But when i run the npm with "npm run it", it shows me the error of
WARNING in configuration
The 'mode' option has not been set. Set 'mode' option to 'development' or 'production' to enable defaults for this environment.
ERROR in multi -dev-derver/client?http://localhost:8080 webpack/hot/dev-server ./src
Module not found: Error : Cant resolve './src' in D:\React Js \LearnReact' #multi -dev-derver/client?http://localhost:8080 webpack/hot/dev-server ./src
i ?wdm?: failed to Compile.
Please help me i am really stuck and want to know the solution.
You need to add pass the --config option to webpack-dev-server:
webpack-dev-server --config path/to/webpack.config.js
Also set your mode to development in your base config, you can overwrite it later when you do a production build.
Also ensure that your ./script.js file is in the root of your project, i.e next to your package.json since this file path is relative to the npm script execution.
Based on this configuration --> path: path.resolve(__dirname, 'src') all your built assets will end up in a src folder in the root of your project, assuming that is where your webpack.config.js file is (this path is relative to your config file). The actual folder will only be generated in production, in development assets are stored in memory.
You might also want to set a publicPath:
output: {
...
publicPath: '/'
}
I would also recommend using the html-webpack-plugin since this can resolve the correct paths to your js file for you.
var HtmlWebpackPlugin = require('html-webpack-plugin');
...
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html', // name of file that will be outputted to 'src' when built
template: // path to your html file relative to config
inject: true
})
]
Then you don't have to include the path to your script, so your html file would look like:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div class="first"></div>
</body>
</html>
This has got to be one of the strangest issues with webpack i have ever come across...
Check out this bundle breakdown:
react 116.01KB - fair enough
react-dom 533.24KB - seriously WTF
I thought it may be a corruption in my dependencies but nuking node_modules and reinstalling doesn't have any effect. I guess it's something to do with the way webpack is bundling it but i'm lost for ideas. The way i'm handing .js imports is pretty stock standard.
// webpack.config.js
const path = require('path');
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const Dashboard = require('webpack-dashboard');
const DashboardPlugin = require('webpack-dashboard/plugin');
const dashboard = new Dashboard();
module.exports = {
context: path.join(__dirname, 'src'),
entry: {
bundle: './index.js',
},
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'build'),
},
module: {
rules: [
{
test: /\.html$/,
use: 'file-loader?name=[name].[ext]',
},
{
test: /.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
'css-loader',
'postcss-loader',
],
}),
},
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader',
},
],
},
plugins: [
// new BundleAnalyzerPlugin(),
new ExtractTextPlugin('styles.css'),
new DashboardPlugin(dashboard.setData),
],
devServer: {
quiet: true,
},
};
// .babelrc
{
"presets": [
"react",
"es2015"
],
"plugins": ["transform-object-rest-spread"]
}
http://elijahmanor.com/react-file-size/
In v15.4.0 the file size of react-dom grew from 1.17kB to 619.05kB. Which means my webpack setup isn't doing anything wrong bundling files. The reason why this module grew so large is because code was transferred from the react module.
I had to change my webpack.config.js, from
devtool: 'inline-source-map'
to
devtool: 'source-map'
Now it generates a much smaller .js + a separate .js.map file, for each of the chunks.
Notice the JS size is even less than react-dom.production.min.js in node_modules:
If you look into the corresponding folders under the node_modules folder, and note the file sizes, you'll see that there's nothing to be surprised about:
That is, the size of the bundle grows noticeably because the size of react-dom.js is large.
Add this following commands at plugins to minify your imports:
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.DefinePlugin(GLOBALS),
new webpack.optimize.UglifyJsPlugin(),
You should create a file or option to production bundle to use this plugins
I need to disable AMD on 4 files and load video.js first before loading the other 3 files, because they depend on it. When I tried doing it in webpack.config.js like so:
const path = require('path')
const webpack = require('webpack')
module.exports = {
entry: './src/main.js',
output: {
path: __dirname + '/public',
filename: 'bundle.js'
},
devServer: {
inline: true,
contentBase: './src',
port: 3333
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
})
],
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules|lib/,
loader: 'babel',
query: {
presets: ['es2015', 'react', 'stage-2'],
plugins: ['transform-class-properties']
}
},
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /[\/\\]lib[\/\\](video|playlist|vpaid|overlay)\.js$/,
exclude: /node_modules|src/
loader: 'imports?define=>false'
}
]
}
}
It doesn't really work, because it just loads video.js (with disabled AMD) and completely ignores the other 3 files.
My folder structure is like so:
▾ lib/
overlay.js
playlist.js
video.js
vpaid.js
▸ node_modules/
▾ public/
200.html
bundle.js
▾ src/
App.js
index.html
main.js
LICENSE
package.json
README.md
webpack.config.js
Now, I found something that takes me 1 step back, because now even video.js doesn't load:
require('imports?define=>false!../lib/video.js')
require('imports?define=>false!../lib/playlist.js')
require('imports?define=>false!../lib/vpaid.js')
require('imports?define=>false!../lib/overlay.js')
and instead just throws these kinds of warnings:
WARNING in ./~/imports-loader?define=>false!./lib/video.js
Critical dependencies:
15:415-422 This seems to be a pre-built javascript file. Though this is possible, it's not recommended. Try to require the original source to get better results.
# ./~/imports-loader?define=>false!./lib/video.js 15:415-422
WARNING in ./~/imports-loader?define=>false!./lib/playlist.js
Critical dependencies:
10:417-424 This seems to be a pre-built javascript file. Though this is possible, it's not recommended. Try to require the original source to get better results.
# ./~/imports-loader?define=>false!./lib/playlist.js 10:417-424
WARNING in ./~/imports-loader?define=>false!./lib/vpaid.js
Critical dependencies:
4:113-120 This seems to be a pre-built javascript file. Though this is possible, it's not recommended. Try to require the original source to get better results.
# ./~/imports-loader?define=>false!./lib/vpaid.js 4:113-120
WARNING in ./~/imports-loader?define=>false!./lib/overlay.js
Critical dependencies:
10:416-423 This seems to be a pre-built javascript file. Though this is possible, it's not recommended. Try to require the original source to get better results.
# ./~/imports-loader?define=>false!./lib/overlay.js 10:416-423
So, my question is, how can I make this work in webpack.config.js so that I don't get these warnings?
I have solved the problem! To make this work you need this:
{
test: /[\/\\]lib[\/\\](video|playlist|vpaid|overlay)\.js$/,
exclude: /node_modules|src/
loader: 'imports?define=>false'
}
and this
require('script-loader!../lib/video.js')
require('script-loader!../lib/playlist.js')
require('script-loader!../lib/vpaid.js')
require('script-loader!../lib/overlay.js')
together!
Now, if you use this (instead of script-loader):
require('imports?define=>false!../lib/video.js')
require('imports?define=>false!../lib/playlist.js')
require('imports?define=>false!../lib/vpaid.js')
require('imports?define=>false!../lib/overlay.js')
It's not gonna work! (you need both imports-loader and script-loader working in unison.
I'm trying to use bootstrap through webpack and have installed it using npm. I want to use it in my react project so I've done the below settings but I keep getting the below error:
main.js
import React from 'react'
import 'bootstrap/dist/css/bootstrap.css'
const Main = () => (
<div className="container">yo</div>
)
Webpack config
var path = require('path');
var webpack = require('webpack');
module.exports = {
devtool: 'source-map',
entry: [
'webpack-hot-middleware/client',
'./client/pokeapp'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/static/'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
],
module: {
loaders: [
// js
{
test: /\.js$/,
loaders: ['babel'],
include: path.join(__dirname, 'client')
},
// CSS
{
test: /\.css$/,
include: path.join(__dirname, 'client'),
loader: 'style-loader!css-loader'
},
{ test: /\.(woff|woff2|eot|ttf|svg)$/, loader: 'url'}
]
}
};
Console Error
Module parse failed: /Users/jlei/Desktop/pokeapp/node_modules/bootstrap/dist/css/bootstrap.css Unexpected token (7:5)
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token (7:5)
at Parser.pp$4.raise (/Users/jlei/Desktop/pokeapp/node_modules/acorn/dist/acorn.js:2221:15)
at Parser.pp.unexpected (/Users/jlei/Desktop/pokeapp/node_modules/acorn/dist/acorn.js:603:10)
at Parser.pp.semicolon (/Users/jlei/Desktop/pokeapp/node_modules/acorn/dist/acorn.js:581:61)
at Parser.pp$1.parseExpressionStatement (/Users/jlei/Desktop/pokeapp/node_modules/acorn/dist/acorn.js:966:10)
at Parser.pp$1.parseStatement (/Users/jlei/Desktop/pokeapp/node_modules/acorn/dist/acorn.js:730:24)
at Parser.pp$1.parseTopLevel (/Users/jlei/Desktop/pokeapp/node_modules/acorn/dist/acorn.js:638:25)
at Parser.parse (/Users/jlei/Desktop/pokeapp/node_modules/acorn/dist/acorn.js:516:17)
at Object.parse (/Users/jlei/Desktop/pokeapp/node_modules/acorn/dist/acorn.js:3098:39)
at Parser.parse (/Users/jlei/Desktop/pokeapp/node_modules/webpack/lib/Parser.js:902:15)
at DependenciesBlock.<anonymous> (/Users/jlei/Desktop/pokeapp/node_modules/webpack/lib/NormalModule.js:104:16)
# ./client/components/Main.js 27:0-43
What's the unexpected token? Is that due to my loader not working?
I tested your code and there is nothing wrong with the loader However this line include: path.join(__dirname, 'client') is causing the issue if you remove it you can see bootstrap bundling just fine with webpack.
For getting more from webpack you may want to get a separate css file then you can use ExtractTextPlugin to achieve it.
How it work ?
Installation
npm i extract-text-webpack-plugin
Configure it in webpack
{test: /\.css$/, loader: ExtractTextPlugin.extract({ fallbackLoader: 'style-loader', loader: 'css-loader' })}
and add it in plugin
new ExtractTextPlugin('yourStyle.css')
Now you should have a separate css file in browser instead of every css in style tag
How does it work
It moves every require("style.css") in entry chunks into a separate css output file. So your styles are no longer inlined into the javascript, but separate in a css bundle file (styles.css). If your total stylesheet volume is big, it will be faster because the stylesheet bundle is loaded in parallel to the javascript bundle.
Hope it help you.
you don't have to include bootstrap as an npm module. You can download or use CDN to include bootstrap on your html template. You can then apply it on your component by using 'className' attribute instead of 'class'. Try it.
app.use('/css', express.static(__dirname + '/node_modules/bootstrap/dist/css'));
and in your html file:
<link rel="stylesheet" href="/css/bootstrap.min.css">
This method is the same as downloading the bootstrap files to improve latency.
I am getting an error whenever I try to run Webpack. It just says ERROR in missing path. The error goes away when I remove the module key in the configuration below:
module.exports = {
entry: './client/scripts/app.js',
output: {
path: './docs/scripts/',
filename: 'bundle.js'
},
module: {
loaders: [{
test: /\.js$/,
loader: 'ng-annotate!',
exclude: /node_modules|docs\/bower_components/
}],
}
};
Here is the error output:
Hash: 396f0bfb9d565b6f60f0
Version: webpack 1.13.1
Time: 76ms
+ 1 hidden modules
ERROR in missing path
My webpack config sits in the root of my project. The folder structure is below:
client
scripts
app.js
node_modules
docs
scripts
bundle.js
bower_components
webpack.config.js
You have mistake in RegExp, add \ before /
/node_modules|docs\/bower_components/
^^
also after ng-annotate you don't need add !, because you are using only one loader
loader: 'ng-annotate'
^^