webpack file-loader options aren't recognized - reactjs

Being new to webpack, the answer might be staring me down but I don't see it. No matter how I try to pass them along, the file-loader options aren't found.
I'm using file-loader and I'm trying to pass a publicPath (or simply anything, at first) along as an option. I went into the file loader source code and added a log for all the options it detected, but they always come up empty.
webpack.config.prod.js
var path = require('path')
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: [
'./src/index.js'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'idlink-1.1.1.js',
publicPath: ''
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.NoErrorsPlugin(),
new webpack.optimize.UglifyJsPlugin(),
new webpack.DefinePlugin({'process.env.NODE_ENV': '"production"'})
],
module: {
loaders: [
{
exclude: /node_modules/,
loader: 'babel',
query: { presets: ['react', 'es2015', 'stage-1'] }
},
{test: /\.css$/, loader: "style-loader!css-loader" },
{test: /\.scss$/, loaders: ["style", "css", "sass"]},
{test: /\.less$/, loader: "style-loader!css-loader!less-loader" },
{
test: /\.(jpe?g|png|gif|svg|pdf)$/i,
loader: "file",
options: { publicPath: 'https://apps.ixordocs.be/'}
},
{test: /\.gif$/, loader: "url-loader?mimetype=image/png" }
]
},
}
I've also tried with
loader: "file-loader"
as well as added the options as one string like this
loader: "file?name=[name].[ext]&publicPath=https://apps.ixordocs.be/"
Some context info:
I don't want to have a hardcoded publicPath defined in my output: {}, i want to grab it dynamically from a parameter placed on the div that my plugin is loaded into.
I've tried using the __webpack_public_path__ variable and it works, but not for images. The public path is grabbed from the parameter, set, and used to fetch a chunk. Somehow it has no effect on images though. If I hardcode a publicPath under output, it DOES work for images. This leads me to believe there is a problem with the loader's communication to the variable, so the idea is to get the options working and eventually try to pass a dynamic publicPath in there.

Your question is totally valid based on the documentation of the loader on both loader's GitHub repo and webpack docs. The problem is the publicPath and outputPath features are implemented in a pull request that is merged but not yet released to a new version of loader, and the README on npm doesn't mention the features for the same reason.
You can still use these features by installing from the GitHub repo with npm install webpack/file-loader --save-dev and your options should work. If not try replacing options with query.
{
test: /\.(jpe?g|png|gif|svg|pdf)$/i,
loader: "file-loader",
query: { publicPath: 'https://apps.ixordocs.be/'}
}
Using URLs for publicPath is also valid because it happens often that you want to load your assets from a CDN or another server.

Related

Webpack adds every assets to root diretory

I'm trying to implement SSR using React (create-react-app) and Firebase. To do so, I'm currently working on my webpack configuration:
module.exports = [{
entry: './src/index.js',
module: {
rules: [
{test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/},
{test: /\.jsx$/, loader: 'babel-loader', exclude: /node_modules/},
{test: /\.css$/i, use: ['style-loader', 'css-loader']},
{test: /\.(png|jpe?g|gif|svg|otf)$/i, loader: 'file-loader', exclude: /node_modules/},
]
},
output: {
filename: 'public/bundle.js',
path: __dirname
}
}];
The webpack works fine without any errors (some size limit warnings, but from what I've read online I can ignore them). Anyways somehow it's adding every single asset to my root folder (not even inside of my directory), which is kind of ugly and confusing. - How can I change the output target of these assets?
Change your output to
output: {
filename: 'js/bundle.js',
path: path.resolve(__dirname, 'dist/assets')
}
This will put your bundle.js in the dist/assets/js directory inside your project's root.
As another example, if you want your bundle.js in public/js folder in your project's root, configure it like this
output: {
filename: 'js/bundle.js',
path: path.resolve(__dirname, 'public')
}
If you leave out the path option entirely, it'll default to the dist directory.
Or refer this Webpack documentation page and adjust the values accordingly.
Also, don't forget to import the path module
const path = require('path');

Webpack: Can I get a source map for after babel, before minification?

I have a fairly basic webpack setup that runs babel and out comes my minified js with a source map.
Now when I run my source map in chrome I get the js before babel and before minification. However I would often like to have my source map after babel but before minification. Is this possible?
TL;DR I want source map to post-babel pre-minifcation. Possible?
For completeness
I run babel-loader 8 with webpack 4
Here is a screenshot from chrome showing the problem. As you can see the Dropzone tag indicates this is jsx (and so before babel)
Secondly here is my webpack config (not that it actually matters for my question).
const path = require('path');
module.exports = {
context: path.join(__dirname, 'Scripts', 'react'),
entry: {
client: './client'
},
output: {
path: path.join(__dirname, 'Scripts', 'app'),
filename: '[name].bundle.min.js'
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
plugins: [require('#babel/plugin-proposal-object-rest-spread')],
presets: ["#babel/es2015", "#babel/react", "#babel/stage-0"]
}
}
}
]
},
resolve: {
extensions: ['.js', '.jsx']
},
externals: {
// Use external version of React (from CDN for client-side, or
// bundled with ReactJS.NET for server-side)
react: 'React'
},
devtool: 'source-map'
};
Running webpack with -d gives a second set of source maps in chrome that does the trick.

Can I set a "scope" for dependencies bundled by webpack?

I use webpack to to bundle a ReactJS component. This ReactJS component has some dependencies and one of them is jQuery. Right now I just run webpack to create the bundled script.
Now I'd like to integrate the bundled script (representing my ReactJS component) into a legacy application. This application uses another version of jQuery (by directly importing the jQuery javascript file).
I wonder if this can lead to any problems because of having two jQuery versions in one application.
I don't really understand how webpack handles the dependencies in the bundle. Are they kind of "scoped" in the bundle so that they don't affect parts of my legacy application? Or is there any way to do so?
My webpack.config:
var CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
entry: "./js/components/Application.js",
output: {
path: "./target/dist",
filename: "application.js"
},
module: {
loaders: [
{
loader: "babel-loader",
test: /\.js$/,
exclude: /(node_modules|dist|__tests__)/
},
{
loader: "style-loader!css-loader",
test: /\.css$/
},
{
test: /\.(jpg|png)$/,
loader: 'url-loader',
include: /img/
}
]
},
devtool: 'source-map',
plugins: [
new CopyWebpackPlugin([
{from: 'static/index.html'},
{from: 'css/*.css'},
{from: 'fonts/*'},
{from: 'img/*.*'},
{from: 'data/*'}
])
]
};

Inline image loading..webpack

I am pulling my hair off...
Feels like I have tried everything.
This is my webpack config:
var publicConfig = {
context: path.join(__dirname, 'src'),
entry: [
'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000',
'./public.jsx',
],
output: {
path: path.join(__dirname, 'app'),
filename: 'publicBundle.js',
publicPath: '/assets/',
},
module: {
loaders: [
{ test: /\.jsx?$/, exclude: /node_modules/, loader: 'babel-loader'},
//{ test: /\.css$/, loader: 'style!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]' },
// { test: /\.css$/, loader: 'style!css-loader?modules&importLoaders=1&localIdentName=[name]' },
{ test: /\.css$/, loader: "style!css" },
{
test: /\.(jpg|png)$/,
loader: 'url?limit=25000'
},
{ test : /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/, loader : 'file-loader' }
]
},
resolve: {
extensions: ['', '.js', '.jsx', '.json']
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
]
};
When defining images in my css files the images gets added to the /assets/ folder, which is exactly what I want... However, I want to be able to call image paths from inline ( the html views aswell ). But the images doesnt get copied to /assets/ unless I target them from my css file.
I tried importing them by:
import logo from './images/animus_logo_blacktext.png'
But it still doesnt appear in my assets.
What is the best practice for image paths inline?
Is it possible the images are very small? The limit you configured in URL-loader means that all images under 25000 bytes will be inlined (as data URI's) instead of served as a file. Files larger than 25000 bytes will be treated by url-loader the same way file-loader treats them.
I think you want to try https://www.npmjs.com/package/copy-webpack-plugin. This is a webpack plugin that copies individual files or entire directories to the build directory.
Switch to the file-loader instead of the url loader. The images may be under your limit of 25000 (25kb).
Without modifying your webpack configuration you could try this:
import logo from 'file-loader!./images/animus_logo_blacktext.png'
You should see the image in your assets.

Webpack with babel-loader for react corrupts image files

I am using webpack with babel-loader to transform .jsx react files.
However, adding a file-loader or style- and css-loader does not correctly process the images required() in the react components or style sheets.
They get recognized by webpack and copied to the dist folder. The path to the image file is correct, I've verified this in the css and js output.
The server is also able to display the files, I've checked with some manually copied ones.
What is happening is that the images themselves get corrupted. No image viewer nor the browser can display the image which results in an invisible image in the browser.
What I've tried so far:
using only babel-loader as suggested in: https://github.com/webpack/file-loader/issues/35, results in Error: No handler for file type.
using file-loader directly
using image-webpack-loader (which seems to be using file-loader under the hood)
using IsomorphicLoaderPlugin (https://github.com/jchip/isomorphic-loader) which seems to be a simpler alternative to webpack-isomorphic-tools
using css background-images with url() and ExtractTextPlugin('style-loader", 'css-loader')
All of the above steps resulted in either errors with webpack not finding an appropriate handler or corrupted image files.
Here is my current webpack config for reference (I've included all of it in case there are any problems/conflicts I am overlooking):
var ExtractTextPlugin = require('extract-text-webpack-plugin'),
webpack = require('webpack');
IsomorphicLoaderPlugin = require("isomorphic-loader/lib/webpack-plugin");
module.exports = {
context: __dirname + '/client',
entry: ['babel-polyfill', './index.jsx'],
output: {
filename: 'app.js',
path: __dirname + '/dist',
publicPath: '/'
},
resolve: {
ignore: /node_modules/,
extensions: ['', '.js', '.jsx']
},
devtool: 'source-map',
plugins: [
new ExtractTextPlugin('styles.css'),
new IsomorphicLoaderPlugin({ keepExistingConfig: false }),
new webpack.DefinePlugin({
"process.env": {
BROWSER: JSON.stringify(true)
}
})
],
module: {
preLoaders: [
{
loaders: ['isomorphine']
}
],
loaders: [
{
test: /\.jsx?$/,
loader: 'babel',
exclude: /node_modules/,
query: {
cacheDirectory: true,
plugins: ['transform-runtime', 'transform-decorators-legacy', 'transform-class-properties', 'transform-object-rest-spread'],
presets: ['react', 'es2015', 'stage-0']
}
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader')
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loader: "file!isomorphic"
}
]
}
};

Resources