How to add a js file with webpack? - javascript

I was reading this webpack tutorial:
https://webpack.github.io/docs/usage.html
It says it bundles the src files and node_modules. If I want to add another .js file there, how can I do this? This is a thirdpartyjs file that is not part of the source and not part of the node_modules files. This is my current webpack.config.js:
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: [
'react-hot-loader/patch',
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/only-dev-server',
'./app/app.js'
],
output: {
path: path.resolve(__dirname, "dist"),
publicPath: "/dist/",
filename: "dist.js",
sourceMapFilename: "dist.map"
},
devtool: 'source-map',
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('development')
}
}),
],
module: {
loaders: [{
loader: 'babel',
exclude: /node_modules/
}]
},
devServer: {
inline: true
},
node: {
fs: "empty"
},
watch: false
}

The start point for code is the entry field in config. In your config entry point is the list of files. Webpack gets all, resolve their dependencies and output in one file.
You have two options for adding third party script:
add the file path to entry list before app.js
require this file from app.js

In response to Dmitry's answer:
add the file path to entry list before app.js
This has the effect that you will get a bundled .js file for each entry point, which you might not want.
require this file from app.js
You might not have access to app.js if it is written dynamically, or for whatever reason you might not want to edit app.js.
Another option:
You can use webpack-inject-plugin to inject any JS code as string into the resulting .js bundle created by webpack. This way you can read the File you want to inject as a string (e.g. fs.readFile in nodejs) and inject it with the plugin.

Another solution but without using any extra plugins:
//Webpack.config.js
entry: {
main: './src/index',
/**
/* object is passed to load script at global scope and exec immediately
/* but if you don't need then simply do:
/* myCustomScriptEntry: './src/myCustomScript'
*/
myCustomScriptEntry: {
import: './src/myCustomScript',
library: {
name: 'myCustomScriptEntry',
type: 'var',
},
},
},
new HtmlWebpackPlugin({
template: './public/index.html',
excludeChunks: ['myCustomScriptEntry'], //exclude it from being autoreferenced in script tag
favicon: './public/favicon.svg',
title: 'Alida',
}),
and
//index.html
<script type="text/javascript" src="<%= compilation.namedChunks.get('myCustomScriptEntry').files[0] %>"></script>

Related

React import images from public folder

I'm trying to get static images fro my public directory but is not being found. I'm not using CRA, so maybe is some configuration with Webpack that I'm missing. Using file-loader module and importing the image works on Dev Mode, but doesn't work in for my production server specification
My Project structure:
\public
\static
\images
image.png
\src
\component
component.js
...
package.json
webpack.common.js
webpack.dev.js
webpack.prod.js
On component.js, I want to get image.jpg on static/images folder like this:
<img src='/static/images/image.png'></img>
But I'm getting a 404 not found.
My webpack.commom.js:
const CleanWebPackPlugin = require('clean-webpack-plugin')
const HtmlWebPackPlugin = require('html-webpack-plugin')
const path = require('path')
module.exports = {
entry: {
main: './src/index.js'
},
output: {
filename: '[name].[hash].js',
path: path.resolve('./dist'),
publicPath: "/"
},
module:{
rules:[
{
test: /\.js$/,
exclude: ['/node_modules'],
use: [{ loader: 'babel-loader'}],
},
{
test: /\.s?(a|c)ss$/,
use: [{
loader: 'style-loader'
}, {
loader: 'css-loader'
},{
loader: 'sass-loader'
}]
},
{
test: /\.(png|jpe?g|gif)$/,
use: [
{
loader: 'file-loader',
options: {},
},
],
},
]
},
plugins: [
new HtmlWebPackPlugin({
template: 'index.html'
}),
new CleanWebPackPlugin(),
],
}
And the Dev version:
module.exports = merge(common, {
mode: 'development',
devServer: {
host: 'localhost',
port: 3000,
open: true,
historyApiFallback: true,
publicPath: "/",
}
})
Thank you in advance.
I assume you want to display such image more than once. In that case, is annoying to keep writing something like '%PUBLIC_URL%/img/static/images/image.png' or {process.env.PUBLIC_URL + '/img/static/images/image.png'} two, three or more times within your jsx code. Basically, without a plugin is imposible to import images from the public folder if your app is rooted in the src folder. However I did find a solution for me and was quite simple in fact. It was something like this:
import React from 'react'
var path = process.env.PUBLIC_URL;
var image = "/img/static/images/image.png";
and then, within jsx code:
<img src={path + image}/>
it worked for me, hope this is helpful for anyone! :D
You are using file-loader as webpack plugin, which does not work in the way of "just mirroring the directory structure of public to dist". You can find the documentation for that plugin here: https://webpack.js.org/loaders/file-loader/
Basically, what the plugin does is, if you import an image file (actually programatically importing it, not just using a string reference to its path), the file is copied to your dist directory, potentially renamed and than in your compiled source code the proper file name is inserted.
So in your case, if you want to solve your problem using file-loader, you would reference the image file like
// Relative path to image file from js file
import imageFile from './assets/image.png';
// ...
const component = props => <img src={imageFile}></img>;
If you want to use the approach of actually just mirroring a public-directory to the dist directory, you need to use an additional webpack-plugin for that (e.g. https://stackoverflow.com/a/33374807/2692307)
By the way, I assume it works in dev-mode because you are setting '/' as public path, so the development server just serves everything in the root directory as well. That is something different than copying the files to dist however as you are trying to achieve.
Not sure if this help but I'm will give it a try
Try to add public path to your dist folder also something like this
output: {
path: path.resolve(__dirname, "/dist"),
filename: "[name].js",
publicPath: "/dist/"
},

Webpack: load js modules dynamically from a URL at runtime

I am currently working on a library which should dynamically load a JavaScript from a remote host and instantiate that.
I am writing the library in TypeScript and my plan is to use Webpack as a bundler.
On another host (remote system) runs a provider which should serve JavaScript code (see here: https://stubs.d-koppenhagen.de/stubs/SimpleStub.js).
The library will dynamically resolve "Identitys" via Webfinger. These Identitys represented by an object and they having a property pointing to a "Stub Provider" which will serve JavaScript code (the link I mentioned before). My library should load this script during runtime (s the library don't know the target for this stubs before) and should use it.
currently my webpack.config.js looks like the following:
var path = require('path');
var webpack = require('webpack');
var WebpackBuildNotifierPlugin = require('webpack-build-notifier');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const PATHS = {
src: path.join(__dirname, './src'),
build: path.join(__dirname, './dist')
};
module.exports = {
entry: {
wonder: PATHS.src + '/wonder'
},
output: {
path: PATHS.build,
filename: '[name].js',
library: 'Wonder',
libraryTarget: 'umd'
},
devtool: 'source-map',
module: {
loaders: [
{
test: /\.ts$/,
loader: 'ts-loader'
}
]
},
resolve: {
extensions: ['.ts', '.js']
},
plugins: [
new WebpackBuildNotifierPlugin()
]
};
And here is a part of the library code:
require.ensure([], function() {
require(localMsgStubUrl);
});
When I am now including the bundled library in an example app, I will get the following error:
Error: loading chunk failed
So is there a way to tell webpack not to bundle the code which is required from a external resource loaded from a URL so that I can use that code like it is?
I don't want to tell webpack the URL statically in a config as maybe other stubs I am loading are located on a different target.
Thanks in advance for your help!

Entry module not found: Error: Can't resolve './src/index.js'

I was installing a react startup app and added Webpack, but it says Can't resolve './src/index.js'.
Browser Shows
My Files Path and Package.json Contents
Webpack.config.js Contents
var debug = process.env.NODE_ENV !== "production";
var webpack = require('webpack');
var path = require('path');
module.exports = {
context: path.join(__dirname, "public"),
devtool: debug ? "inline-sourcemap" : false,
entry: "./src/index.js",
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2016', 'stage-0'],
plugins: ['react-html-attrs', 'transform-decorators-legacy', 'transform-class-properties'],
}
}
]
},
output: {
path: __dirname + "/public/",
filename: "build.js"
},
plugins: debug ? [] : [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }),
],
};
Your base URL is path.join(__dirname, "public"), and your entry is ./src/index.js. Webpack tries to find ./src/index.js in public dir; obviously it does not exist. You should modify entry to ../src/index.js.
The other way I find out to fix this problem is to use path.resolve().
const path = require('path');
module.exports = {
mode: "production",
entry: path.resolve(__dirname, 'src') + 'path/to/your/file.js',
output: {
/*Webpack producing results*/
path: path.resolve(__dirname, "../src/dist"),
filename: "app-bundle.js"
}
}
This will make sure, webpack is looking for entry point in src directory.
By the way it's the default entry point. You can also change this entry point to your suitable location. Just replace the src directory with the other directory you want to use.
My webpack.config.js was named Webpack.config.js and the new cli was looking for something case-sensitive.
Webpack does not look for .js files by default. You can configure resolve.extensions to look for .ts. Don't forget to add the default values as well, otherwise most modules will break because they rely on the fact that the .js extension is automatically used.
resolve: {
extensions: ['.js', '.json']
}
The entry path is relative to the context. It's looking for a file in public/src/ when you want it to look for a path in just /src. Looking at the rest of your webpack.config.js it doesn't seem like you need the context line at all.
https://webpack.js.org/configuration/entry-context/
I had the same problem and found that it was caused by having installed create-react-app globally in the past using npm install -g create-react-app.
As create-react-app should now not be installed globally, I needed to uninstall it first using npm uninstall -g create-react-app and then install it in my project directory with npx create-react-app *my-app-name*.
My solution was to put App.js file on a components folder inside the src folder and keep the inde.js just inside the src one
I had same problem. And solutions was really 'at the top' I forgot to add module.exports inside my webpack.prod.js.
So instead of
merge(common, {
...
});
use
module.exports = merge(common, {
...
});

Concat and minify all less files with Webpack without importing them

I have a folder of around 20 separate less files that I need to concatenate into a single file via Webpack and store this in my /dist folder. My current Webpack config file is as follows:
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
const bundleOutputDir = './wwwroot/dist';
module.exports = (env) => {
const isDevBuild = !(env && env.prod);
return [{
stats: { modules: false },
entry: { 'main': './ClientApp/boot.ts' },
resolve: { extensions: ['.js', '.ts'] },
output: {
path: path.join(__dirname, bundleOutputDir),
filename: '[name].js',
publicPath: '/dist/'
},
module: {
rules: [
{ test: /\.ts$/, include: /ClientApp/, use: 'awesome-typescript-loader?silent=true' },
{ test: /\.html$/, use: 'raw-loader' },
{ test: /\.css$/, use: isDevBuild ? ['style-loader', 'css-loader'] : ExtractTextPlugin.extract({ use: 'css-loader' }) },
{ test: /\.less/, use: ExtractTextPlugin.extract('style-loader', 'css-loader!less-loader') },
{ test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' }
]
},
plugins: [
new CheckerPlugin(),
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./wwwroot/dist/vendor-manifest.json')
})
].concat(isDevBuild ? [
// Plugins that apply in development builds only
new webpack.SourceMapDevToolPlugin({
filename: '[file].map', // Remove this line if you prefer inline source maps
moduleFilenameTemplate: path.relative(bundleOutputDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk
})
] : [
// Plugins that apply in production builds only
new webpack.optimize.UglifyJsPlugin(),
new ExtractTextPlugin('site.less'),
new ExtractTextPlugin('site.css')
])
}];
};
If I try and import each single .less file into the boot.ts entry file, I get a less error stating that the less variables that I've declared are not being recognised, which is how I came to the conclusion that I need to concat these files beforehand. I come from a gulp background, so any help to get me up and running with this would be greatly appreciated.
If there is an alternative way to get all less compiled to css and working correctly, without the need for concat, then I'm open to suggestions.
Webpack is a module bundler and uses the module syntax for JavaScript (ES6, CommonJS, AMD..), CSS (#import, url) and even HTML (through src attribute) to build the app's dependency graph and then serialize it in several bundles.
In your case, when you import the *.less files the errors are because you miss CSS modules. In other words, on the places where you have used variables defined in other file, that file was not #import-ed.
With Webpack it's recommended to modularize everything, therefore I would recommend to add the missing CSS modules. I had the same issue when I was migrating a project from Grunt to Webpack. Other temporary solution is to create an index.less file where you will #import all the less files (note: the order is important) and then import that file in app's entry file (ex. boot.ts).

webpack configuration webpack-dev-server does not compile files on the fly

I have following webpack configuration file.
const path = require('path');
const webpack = require('webpack');
module.exports = {
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'scripts.min.js'
},
resolve: {
root: [
path.resolve('./src'),
path.resolve('./node_modules')
]
},
entry: './src/app.js',
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel'
}
]
},
devServer: {
// compress: true,
inline: true,
stats: 'errors-only'
},
plugins: [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({ 'mangle': false, sourcemap: false })
]
};
The problem is that when I run webpack-dev-server command, it does run the server but when I make changes to any js file they are not compiled on the fly. So I had to stop the server and run webpack and then run webpack-dev-server command to make things work.
How can I make webpack-dev-server work so that when watches for all js, css, scss files and compile those fly?
If you are working with an IDE, you have to disable "safe write".
Note that many editors support “safe write” feature and have it enabled by default, which makes dev server unable to watch files correctly. “Safe write” means changes are not written directly to original file but to temporary one instead, which is renamed and replaces original file when save operation is completed successfully. This behaviour causes file watcher to lose the track because the original file is removed. In order to prevent this issue, you have to disable “safe write” feature in your editor.
http://webpack.github.io/docs/webpack-dev-server.html#hot-mode

Categories

Resources