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/*'}
])
]
};
Related
I'm trying to set up a tailwind css for my personal project. It's a react SSR application. I'm having an issue with postcss setup under the webpack configuration. It throws the same error on every *.css file (even on the empty ones).
It looks like it can't resolve the configuration file or default options? Tried different configurations, but no effect. Initially, I thought that it could be something with my css files, but they all valid and compile if I remove postcss plugin
webpack config
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ESLintPlugin = require('eslint-webpack-plugin');
const paths = require('./paths');
module.exports = {
entry: {
index: path.resolve(paths.projectSrc, 'index.js'),
},
resolve: {
alias: {
'#src': paths.projectSrc,
},
},
module: {
rules: [
{
test: /.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.html$/,
use: [
{
loader: 'html-loader',
options: { minimize: true },
},
],
exclude: /node_modules/,
},
{
exclude: /node_modules/,
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: path.resolve(__dirname, './client-build/css/'),
},
},
{
loader: 'css-loader',
options: { importLoaders: 1 },
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
config: path.resolve(__dirname, 'postcss.config.js'),
},
},
},
],
},
{
test: /\.(woff2?|ttf|otf|eot|png|jpg|svg|gif)$/,
exclude: /node_modules/,
loader: 'file-loader',
options: {
name: './assets/[name].[ext]',
},
},
],
},
plugins: [
new ESLintPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(paths.public, 'index.html'),
filename: 'index.html',
}),
new MiniCssExtractPlugin({
filename: '[name].bundle.css',
chunkFilename: '[id].css',
}),
new CopyWebpackPlugin({
patterns: [{ from: path.resolve(paths.public, 'assets'), to: 'assets' }],
}),
],
devtool: 'inline-source-map',
};
postcss.config.js
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
console output
This is caused by a breaking change in v5.0.0 of postcss-loader where support for version 4 of webpack was dropped.
README which states:
Changelog
All notable changes to this project will be documented in this file. See standard-version for commit guidelines.
5.0.0 (2021-02-02)
⚠ BREAKING CHANGES
minimum supported webpack version is 5
How to fix it
You will need to downgrade postcss-loader to v4.2.
Side Note for Angular Projects
In case this helps other readers: You may not just see this in React projects. I found this issue after upgrading an Angular 8 project to Angular 11.
While I can't help with React projects, this Angular hint may also be of use anyways.
If you are on an Angular project and you've already tried to fix this issue by upgrading to v5 of webpack and then ran into dependency issues with libraries using v4 of webpack - You will want to follow these steps.
Downgrade postcss-loader to v4.2 as mentioned above.
Remove webpack v5 from package.json.
Delete package.lock.json.
Delete node_modules directory.
Run npm install.
Run ng serve or ng build.
Tell the boss you fixed it.
After this, you should be good to go with tailwindcss and Angular.
I am looking to migrate the existing Ruby based build system in our AngularJS(1.4.X) project to Webpack. The project code is not using JS modules and being with old-school Angular code patter I am not sure how Webpack will find all the controller and factory files in the project.
Folder structure is like,
-app
- assets
- javascripts
- ctrl
- controllerA.js
- controllerB.js
-services
-serviceA.js
-serviceB.js
- angular.min.js
- angular-route.js
- main.js
Wen I use the main.js in my entry point it get copied into the build folder but none of the other files as processed by Webpack even if I use babel-loader to .js rule.
One option I can think of is to use all other files into a separate bundle file using something like
https://www.npmjs.com/package/webpack-merge-and-include-globally, but I want to know whether there is a better way of doing it.
My current webpack config is as below.
module.exports = {
context: __dirname +'/app',
entry: {
'app-portal': [
'/assets/javascripts/main.js',
'/assets/javascripts/angular.min.js',
'/assets/stylesheets/portal/style.css',
'/assets/stylesheets/portal/navbar.css',
'/assets/stylesheets/portal/animation.css',
'/assets/stylesheets/portal/bootstrap.min.css',
'/assets/stylesheets/portal/bootstrap-notify.css',
'/assets/stylesheets/portal/fontello.css',
]
},
output: {
path: __dirname + "/dist/assets",
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader:'css-loader',
options: {
sourceMap: true,
url: false,
},
},
],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './views/portal/index.html',
filename: '../index.html',
}),
new MiniCssExtractPlugin({
filename: './[name].css',
linkType: false,
ignoreOrder: false,
}),
new CopyPlugin({
patterns: [
{
from: './views/portal/**/*.*',
to: "../[name].[ext]",
globOptions: {
ignore: [
'**/index.*',
],
},
},
{
from: './assets/fonts/*.*',
to: "./[name].[ext]",
},
{
from: './assets/images/portal/*.*',
to: "./[name].[ext]",
},
{
from: './assets/theme/*.*',
to: "./[name].[ext]",
}
]
}),
],
Probably Webpack is not the right solution for me as I don;t want to change the source code as suggested in Webpack plugins and/or strategies for AngularJS
You can try something like this (we use it for running tests):
bundle.js:
const jsConext= require.context('.', true, /\.js/);
ng1Context.keys().forEach(ng1Context);
const cssConext= require.context('.', true, /\.css/);
ng1Context.keys().forEach(ng1Context);
...
entry: { 'app-portal': 'bundle.js' }
This should work in general (You might need fix order for css or in case of multiple angular modules etc.)
I have a embeddable widget written using react and bundle to a single js file using webpack 4.29.3 and babel 7. Everything works fine in webpack-dev-server and production by just inserting <script type="text/javascript" src="myWidget.js"></script> tag in html. My webpack config is as follows: (I have included babel-polyfill)
const HtmlWebPackPlugin = require("html-webpack-plugin");
module.exports = env => {
let htmlTemplate = "./public/index.html";
return {
entry: [ "#babel/polyfill","./src/index.js"],
output: {
path: __dirname + '/dist',
filename: 'chat.js',
library: 'Chat',
libraryTarget: 'umd',
umdNamedDefine: true
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: htmlTemplate,
filename: "./index.html",
inject: 'head'
})
]
}};
my babel config is as follows:
{
"presets": [
"#babel/env",
"#babel/preset-react"
],
"plugins": [
"#babel/plugin-proposal-class-properties"
]
}
But when I try to embed the widget to a site written in angular 4 it says TypeError: t.finally is not a function though I have include the polyfill in the react webpack build. I found the reason to be that zone.js in angular overrides the babel polyfill. When I updated the host site (angular site) zone.js version from 0.8.14 to 0.8.26 embeddable widget works fine. My question is in actual scenario I have no control on the host site where widget is embed. So in such scenario how can I overcome that?
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.
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.