I have two main directories in my project: "src" and "specs".
The entrypoint of my webpack configuration is set to a file within src. Also the context of the webpack config is set to the src directory. I have a postinstall hook in my package.json which bundles the app into a dist folder whenever the package is installed via "npm install". This also means that the devDependencies are not installed and that is what causes my npm install to fail. Apparently webpack tries to process the files in specs which it cannot do because the devDependencies are not installed.
Any idea why webpack thinks it should process the files in the specs directory?
Here is my complete webpack config:
const path = require("path");
const nodeExternals = require("webpack-node-externals");
const NODE_ENV = "development";
const client = {
entry: path.join(__dirname, "src", "browser_sdk", "index.ts"),
context: path.resolve(__dirname, "src", "browser_sdk"),
target: "web",
mode: NODE_ENV,
devtool: "source-map",
watch: false,
output: {
path: path.resolve(__dirname, "dist"),
filename: "client.js",
library: {
type: "umd",
},
},
module: {
rules: [
{
test: /\.ts$/,
use: "ts-loader",
exclude: /node_modules.*\.js$/,
},
],
},
resolve: {
extensions: [".tsx", ".ts", ".js"],
},
externals: {
"pg-native": "require('pg-native')"
},
optimization: {
minimize: false,
},
};
const server = {
entry: path.join(__dirname, "src", "server", "index.ts"),
context: path.resolve(__dirname, "src", "server"),
mode: NODE_ENV,
target: "node",
externals: [nodeExternals(), 'pg-native'],
watch: false,
devtool: "source-map",
output: {
path: path.resolve(__dirname, "dist"),
filename: "server.js",
library: {
type: "umd",
},
},
resolve: {
extensions: [".ts", ".js"],
},
module: {
rules: [
{
test: /\.ts$/,
use: "ts-loader",
exclude: /node_modules.*\.js$/,
},
],
},
};
module.exports = [server, client];
The following config fixed my problems. I used transpileOnly to prevent the specs directory is bundled and I wrote a custom exclude handler to prevent node_module is bundled.
module: {
rules: [
{
test: /\.tsx?$/,
use: {
loader: "ts-loader",
options: {
transpileOnly: true
},
},
exclude: (e) => {
let file = e.replace(__dirname, '.');
return file.match(/node_modules/)
}
},
],
},
Related
I have the following webpack config:
webpack.common.js:
const path = require('path');
module.exports = {
entry: './src/index.js',
watchOptions: {
ignored: [
path.resolve(__dirname, '.git'),
path.resolve(__dirname, 'node_modules'),
]
},
module: {
rules: [],
},
resolve: {
extensions: ['.js'],
},
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist'),
publicPath: "/dist/",
},
};
webpack.dev.js:
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
devServer: {
open: true,
compress: false,
port: 9000,
http2: false,
https: false,
liveReload: true,
watchFiles: ['src/**/*'],
client: {
overlay: false,
},
static: {
directory: __dirname,
}
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
})
]
});
My folder structure:
webpack.common.js
webpack.dev.js
src/
├─ index.html
├─ index.js
Tools versions:
"html-webpack-plugin": "^5.5.0"
"webpack": "^5.52.0"
"webpack-dev-server": "^4.1.0"
"webpack-merge": "^5.8.0"
QUESTION: When running webpack-dev-server --config webpack.dev.js in the root folder, I'm getting 404 error for index.html when accessing localhost:9000/index.html. Shouldn't index.html be created in memory?
I do get this in the log when starting the server:
asset bundle.js 901 KiB [emitted] (name: main)
asset index.html 5 KiB [emitted]
How not to get 404 error and access index.html that's in memory? Am I missing something?
Maybe this webpack config fix your problem, the index.html may be in a folder "public" and not in "src", and set enable the inject on index.html
Try this config :
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports ={
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.js'
},
resolve: {
extensions: ['.js','.jsx']
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use:{
loader: 'babel-loader'
}
},
{
test: /\.html$/,
use:{
loader: 'html-loader'
}
},
{
test: /\.(css|scss)$/,
use:[
"style-loader",
"css-loader",
"sass-loader"
]
},
{
test: /\.svg$/,
use:{
loader: "svg-url-loader"
}
},
{
test: /\.png$/,
use: [
"file-loader",
{
loader: "image-webpack-loader"
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "./public/index.html",
inject:true,
filename: 'index.html'
}),
new MiniCssExtractPlugin(),
],
devServer:{
static: {
publicPath: path.join(__dirname, 'dist')
},
open:true,
compress: true,
port: 3000
}
}
My problem was with this line in webpack.common.js:
publicPath: "/dist/"
By removing it, it worked.
I have a webpack configuration that generates the react bundle when i call webpack directly.
Since i would like to incorporate hot reloading i need to run the webpack dev server alongside my development express server (serving API endpoints) that runs on port 3000
webpack.dev.config.js
const webpack = require('webpack');
const merge = require('webpack-merge');
const Jarvis = require('webpack-jarvis');
const path = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = merge({}, {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
output: {
chunkFilename: '[name]-[hash].js',
publicPath: "http://localhost:3000/build/",
crossOriginLoading: 'anonymous'
},
optimization: {
noEmitOnErrors: true,
namedModules: true,
},
plugins: [
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new HtmlWebpackPlugin({
inlineSource: '.(js|css)$',
inject: 'head',
filename: path.join(__dirname, "/dist/index.html"),
template: path.join(__dirname, "/public/index.html"),
chunks: ['common', 'main']
}),
new Jarvis({port: 7003}),
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({
_DEVELOPMENT_: true,
})
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: { presets: ["es2015", "react", "stage-0"] }
}
},
{
test: /\.jsx$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: { presets: ["es2015", "react", "stage-0"] }
}
},
{
test: /\.scss$/,
use: [
"style-loader", // creates style nodes from JS strings
"css-loader", // translates CSS into CommonJS
"sass-loader" // compiles Sass to CSS, using Node Sass by default
]
},
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: ["file-loader"]
},
{
test: /\.svg$/,
use: {
loader: "svg-inline-loader"
}
},
{
test: /\.ts$/,
use: [
{
loader: "ts-loader",
options: {
compilerOptions: {
declaration: false,
target: "es5",
module: "commonjs"
},
transpileOnly: true
}
}
]
}
]
},
resolve: {
alias: {
'react-dom': '#hot-loader/react-dom'
}
},
entry: {
main: [
'babel-polyfill',
'react-hot-loader/patch',
'webpack/hot/only-dev-server',
'webpack-dev-server/client?https://0.0.0.0:7001',
'./src/index.jsx',
],
}
});
dev-server.js
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const config = require('./webpack.dev.config');
new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
headers: {'Access-Control-Allow-Origin': '*'},
hot: true,
https: true,
clientLogLevel: 'error',
overlay: true,
historyApiFallback: true,
disableHostCheck: true,
watchOptions: {
ignored: /\/node_modules\/.*/,
},
stats: {
assets: false,
cached: false,
cachedAssets: false,
children: false,
chunks: false,
chunkModules: false,
chunkOrigins: false,
colors: true,
depth: false,
entrypoints: true,
excludeAssets: /app\/assets/,
hash: false,
maxModules: 15,
modules: false,
performance: true,
reasons: false,
source: false,
timings: true,
version: false,
warnings: true,
},
}).listen(7001, '0.0.0.0', function(err, result) {
console.log(`Serving chunks at path ${config.output.publicPath}`);
});
package.json scripts
"scripts": {
"build": "webpack --config webpack.dev.config.js --progress --profile --colors",
"start-dev": "node dev-server.js",
"build-prod": "webpack --config webpack.prod.js --progress --profile --colors",
"start": "node server.js"
},
If i run
npm run build
The result is a new js bundle and html:
dist/main.js
dist/index.html
however the ideal situation is to run
npm run start-dev
which will start the dev server, this outputs that is has successfully built the bundles, but they never appear in my filesystem so there must be an output config that i have not setup correctly in the dev server?
EDIT
Issue turned out to be as described by the post below.
To access the live bundle reloads i edited the bundle public path from the "production server" back to just the build location, and then accessed the page from the devserver instead of the page being served by the "production server"
output: {
chunkFilename: '[name]-[hash].js',
publicPath: "/build/",
crossOriginLoading: 'anonymous',
path: path.join(__dirname, "/dist"),
},
Webpack dev-server don't write your changes to the disk every time you change your source code. Instead, it watches your files change, process it and serve from memory. Check out here as it explains in detail.
I use absolute paths in my React application. But the WebPack throws me a error. ERROR in ./src/index.js Module not found: Error: Can't resolve 'App' in .../client/src' However, my file is located in this folder. How to solve this problem? I saw that I already wrote about similar problems, but I did not find the answer in them
WebPack config
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'build'),
publicPath: '/',
filename: 'bundle.js'
},
resolve: {
extensions: ['.js', '.jsx']
},
module: {
rules: [
{
test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'
},
{
test: /\.css$/, use: ['style-loader', 'css-loader'],
}
]
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: './public/index/html'
}),
new MiniCssExtractPlugin({
filename: 'style.css'
})
]
};
Hierarchy of my files
---project
--client
-public
index.html
-src
'folders'
index.js
App.js
App.css
--package.json
--webpack.config.js
--.babelrc
You can add this to your webpack.config file.
resolve: {
extensions: ['.js', '.jsx'],
alias: {
root: __dirname,
src: path.resolve(__dirname, 'src'),
},
},
Then you can import by
import something from 'src/index.js'
But if you use something else than Webpack, e.g. Jest, Storybook then you would also need to apply that information.
E.g. for Jest
npm install babel-plugin-module-resolver
and update .babelrc to understand absolute path
{
"plugins": [
[
"module-resolver",
{
"extensions": [".js", ".jsx"],
"root": ["./src"],
"alias": {
"root": ".",
"src": "/src"
}
}
]
]
}
I am currently using:
"mocha": "^5.2.0"
"mocha-webpack": "^2.0.0-beta.0"
"webpack": "^4.19.1"
"nyc": "^13.0.1"
and for some reason, I'm getting weird source files.
.tmp/mocha-webpack/1537879911832/webpack:/src
| 61.18 | 29.63 | 64.29 | 61.18 | |
db.js
I'm wondering how this is generated because exclude doesn't work
"nyc": {
"exclude": [
"./tmp/**/*"
],
}
Here's my webpack file
var nodeExternals = require("webpack-node-externals")
const path = require("path")
const webpack = require("webpack")
const webpackConfig = {
mode: "none",
context: path.resolve(__dirname),
resolve: {
extensions: [".js"],
alias: {
"#": path.join(__dirname, "../src"),
}
},
output: {
// use absolute paths in sourcemaps (important for debugging via IDE)
devtoolModuleFilenameTemplate: "[absolute-resource-path]",
devtoolFallbackModuleFilenameTemplate: "[absolute-resource-path]?[hash]"
},
devtool: "inline-cheap-module-source-map",
plugins: [
new webpack.NamedModulesPlugin()
],
target: "node", // webpack should compile node compatible code
externals: [nodeExternals()], // in order to ignore all modules in node_modules folder
}
module.exports = webpackConfig
I got it working by reading this manual: https://github.com/vuejs/vue-test-utils-mocha-webpack-example
The main trick was to install babel-plugin-istanbul and update .babelrc file:
"env": {
"test": {
"plugins": ["istanbul"]
}
}
And package.json looks like:
"nyc": {
"exclude": [
"**/tests/**/*.js",
".tmp/**/*.js",
"webpack.config.js"
]
}
And the webpack.config.js looks like:
var path = require('path')
var webpack = require('webpack')
const nodeExternals = require('webpack-node-externals')
module.exports = {
entry: './src/main.js',
output: {
// use absolute paths in sourcemaps (important for debugging via IDE)
devtoolModuleFilenameTemplate: '[absolute-resource-path]',
devtoolFallbackModuleFilenameTemplate: '[absolute-resource-path]?[hash]',
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js',
'#': path.resolve(__dirname, 'src')
}
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},
devServer: {
historyApiFallback: true,
noInfo: true
},
performance: {
hints: false
},
devtool: 'inline-cheap-module-source-map',
externals: ["fs", nodeExternals()],
mode: 'development',
plugins: [
new webpack.NamedModulesPlugin()
]
}
The page loads up correctly and even logs to client console [WDS] Hot module replacement enabled. But when I make changes to files nothing is reflected on the page. Even on reload. Only when restarting the server.
Not sure if this matter but Im using redux.
webpack.config.js
var precss = require('precss');
var autoprefixer = require('autoprefixer');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'eval-source-map',
entry: __dirname + '/src/index.js',
output: {
path: __dirname + '/build',
filename: 'bundle.js',
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel'
},
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.css$/,
loader: 'style!css?modules!postcss'
},
{
test: /\.(png|jpg|jpeg|gif|woff)$/,
loader: 'url-loader?limit=8192'
}
]
},
postcss: function() {
return [autoprefixer, precss];
},
plugins: [
new HtmlWebpackPlugin({
template: __dirname + '/src/index.html'
}),
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './public',
colors: true,
historyApiFallback: true,
inline: true,
hot: true
},
jest: {
moduleFileExtensions: ["js", "jsx"]
}
};
.babelrc
{
"presets": ["react", "es2015", "stage-0"],
"env": {
"development": {
"plugins": [["react-transform", {
"transforms": [{
"transform": "react-transform-hmr",
"imports": ["react"],
// this is important for Webpack HMR:
"locals": ["module"]
}]
// note: you can put more transforms into array
// this is just one of them!
}]]
}
}
}
Try adding
"scripts": {
"start": "node_modules/.bin/webpack-dev-server --progress --inline"
},
in your package.json file, and use npm start.
adding additional entry point in webpack config will reload the page automatically, however you will loose all the state because of a refresh.
entry: [
'webpack-hot-middleware/client?reload=true',
__dirname + '/src/index.js',
],
and in server js
app.use(require('webpack-hot-middleware')(compiler));