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.)
Related
When upgrading from Webpack 4 to Webpack 5, I'm getting issues with css-loader saying "resource not found" or "cannot resolve module xyz". It works up until v3.
In Webpack 5, file loader is deprecated so I was trying to move away from it but it seems something is confusing the other.
Project Structure
- dist
- assets
- fonts
- src
- assets
- css
- fonts
- img
- js
- pdf
- ....
- styles
- custom
- fonts
- scss
package.json
webpack.js
...
Working Webpack config
module.exports = {
output: {
publicPath: "/",
filename: "[name].[fullhash].js"
},
entry: {
main: "./src/Index.jsx",
appcss: "./src/styles/scss/app.scss",
customcss: "./src/styles/custom/main.scss"
},
module: {
rules: [
// Javascript and JSX
{
test: [/\.js$/, /\.jsx$/],
exclude: /node_modules/,
use: ["babel-loader"],
resolve: {
extensions: [".js", ".jsx"]
}
},
// SASS scss files
{
test: [/\.css$/, /\.scss$/],
use: [
{ loader: "style-loader" },
{ loader: "css-loader" },
{ loader: "sass-loader" }
]
},
// {
// test: /\.(woff2?|gif|ttf|otf|eot|svg|png|jpg)$/,
// type: "asset/resource"
// },
// Fonts
{
test: /\.(woff2?|gif|ttf|otf|eot|svg|png|jpg)$/,
// type: "asset/resource"
loader: "file-loader",
options: {
name: "[path][name].[ext]",
outputPath: "fonts/"
}
}
]
},
plugins: [
new CopyPlugin({
patterns: [
{ from: "src/assets", to: "assets" },
{ from: "src/styles/custom/assets", to: "assets/custom" }
]
}),
new CaseSensitivePathsPlugin(),
// Generates HTML file output with the bundles referenced in <script> and <link> elements
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
}),
new ESLintPlugin({
extensions: ["js", "jsx"],
failOnError: false
})
],...
I think the confusion is that some assets are fonts and some are regular assets and I'm not quite sure how to set it up so that each go in a separate folder.
Versions
file-loader: 6.2.0
css-loader: 3.6.0 // Any version higher breaks
Any help appreciated,
Thanks!
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'm working on a React project that gets served by a Go application.
I've been trying to integrate a component library, first with Ant Design, and now with Material UI.
In both instances, as soon as I add a simple component (in this case a Button), my webpack bundle throws net::ERR_CONTENT_LENGTH_MISMATCH in Chrome.
Before adding a component library, my outputted bundle is around 1mb, when adding Material it grows to about 5.5mb, with Ant it was about 11mb.
The strange behavior is that this only happens when I bundle the resources in the development mode configuration with Webpack. If I build for production, everything is fine, although I do get the warning about the bundle size exceeding the recommended limit.
My webpack looks like this:
const path = require("path");
const webpack = require("webpack");
const dotenv = require("dotenv-webpack");
const miniCSS = require("mini-css-extract-plugin");
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
entry: path.resolve(__dirname, "src/index.tsx"),
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/anx.js",
},
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: [".ts", ".tsx", ".js"],
alias: {
components: path.resolve(__dirname, "src/components"),
containers: path.resolve(__dirname, "src/containers"),
src: path.resolve(__dirname, "src"),
},
},
plugins: [
new miniCSS({
filename: "css/anx.css",
}),
],
module: {
rules: [
{
test: /\.ts(x?)$/,
exclude: /node_modules/,
use: [
{
loader: "ts-loader",
},
],
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [
{
loader: miniCSS.loader,
options: {
publicPath: "/dist/css",
},
},
"css-loader",
],
},
{
test: /\.s[ac]ss$/,
use: [
{
loader: miniCSS.loader,
options: {
publicPath: "/dist/css",
},
},
"css-loader",
"sass-loader",
],
},
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{
enforce: "pre",
test: /\.js$/,
loader: "source-map-loader",
},
],
},
// When importing a module whose path matches one of the following, just
// assume a corresponding global variable exists and use that instead.
// This is important because it allows us to avoid bundling all of our
// dependencies, which allows browsers to cache those libraries between builds.
externals: {
react: "React",
"react-dom": "ReactDOM",
},
};
if (process.env.NODE_ENV === "production") {
module.exports.devtool = "source-map";
module.exports.mode = "production";
module.exports.optimization = { minimize: true };
module.exports.plugins = (module.exports.plugins || []).concat([
new CopyPlugin([
{
from: "node_modules/react/umd/react.production.min.js",
to: "js/react.js",
},
{
from: "node_modules/react-dom/umd/react-dom.production.min.js",
to: "js/react-dom.js",
},
]),
new webpack.DefinePlugin({
"process.env": {
NODE_ENV: '"production"',
},
}),
new webpack.LoaderOptionsPlugin({
minimize: true,
}),
]);
} else {
module.exports.devtool = "eval-source-map";
module.exports.mode = "development";
module.exports.plugins = (module.exports.plugins || []).concat([
new CopyPlugin([
{
from: "node_modules/react/umd/react.development.js",
to: "js/react.js",
},
{
from: "node_modules/react-dom/umd/react-dom.development.js",
to: "js/react-dom.js",
},
]),
new dotenv({ path: "secrets/.env.dev" }),
]);
}
I suspect that, in development mode, Webpack includes the source maps and the bundle balloons in size, and this somehow results in the content mismatch error. However, I'm not totally sure. Any help would be appreciated
edit: I found a working solution for this by replacing eval-source-map with source-map in the development environments devtool. I'm not totally sure why this works; my suspicion is that it has something to do with my project running on WSL and the bundle sizes that are produced.
In my angularJs 1.3 application, earlier I was using bower and grunt and it was working fine. I was adding files in my index.html like the following screenshot. But now I have installed all the packages using NPM and using WEbPack 4.21.0 for bundling and run the application. But now if I remove the packages link from Index.html file my application stops working. But I don't want all those links in Index.html and just want to generate a bundle file from those files. Kindly guide me how can I achieve this? Currently, its just adding angular.js file and few other files in vendor.js.
Index.html
Package.json
webpack.config.js
Updated Question:
Now i am using following webpack.config.js but its creating bootstrap_and_some_plugin.css.js . It has to create css file but don't know why it's creating js file?
module.exports = {
context: __dirname + '/app/scripts',
resolve: {
modules: ['bower_components', 'node_modules'],
alias: {
bower_components: __dirname + '/app/bower_components',
assets: __dirname + '/app/assets'
},
extensions: ['.js', '.jsx', '.css']
},
module: {
rules: [
{
test: /\.css$/,
use: [
{ loader: "style-loader" },
{ loader: "css-loader" }
]
},
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
}
}]
}
]
},
entry: {
app: './main-app.js',
'bootstrap_and_some_plugin.css': [
'bower_components/font-awesome/css/font-awesome.css',
'bower_components/seiyria-bootstrap-slider/dist/css/bootstrap-slider.min.css',
'bower_components/angular-ui-tree/dist/angular-ui-tree.min.css',
]
},
output: {
filename: '[name].js',
path: __dirname + '/app/scripts',
//chunkFilename: '[id].[chunkhash].js',
},
devServer: {
contentBase: './app',
host: 'localhost',
port: '9000',
inline: true,
compress: true,
proxy: {
'/api/**': {
//target: 'http://10.189.1.159:8080',
target: 'http://localhost:9100',
secure: false,
changeOrigin: true,
cookieDomainRewrite: true
}
},
open: true
},
plugins: [
]
};
In the file webpack.config.js, you add this property inside the resolve property:
resolve: {
alias: {
bower_components: __dirname + '/app/bower_components'
}
}
In the file main-app.js, if you want to use some js file, you call like this:
require('bower_components/jquery/dist/jquery.js');
require('bower_components/angular/angular.js');
require('bower_components/bootstrap/dist/js/bootstrap.js');
// ...
You need to specify the path of the file webpack.config.js. In my example, all the path looks like:
your_project
webpack.config.js
app
bower_components
jquery
...
angular
...
bootstrap
...
__dirname refers to the current path of the js file which is using it. If you use __dirname inside the webpack.config.js file, it will render your_project. Or using it inside jquery.js, it will render your_project\app\bowser_components\jquery\dist.
Then, build to bundle.js file and delete all the path in the Index.cshtml file.
Hope this helps!
UPDATE: If your js target file goes too big. You can split modules to multiple parts, like this:
entry: {
'bootstrap_and_some_plugin.css': [
'./app/bower_components/bootstrap/dist/css/bootstrap.min.css',
'./app/bower_components/some-plugin/css/some-plugin.css'
],
'jquery_and_angular.js': [
'./app/bower_components/jquery/dist/jquery.js',
'./app/bower_components/angular/angular.js'
],
'site.js': ['./js/site']
}
Then, in your Index.cshtml:
<link href="bootstrap_and_some_plugin.css" rel="stylesheet" />
<!-- body content -->
<script src="jquery_and_angular.js"></script>
<script src="site.js"></script>
UPDATE 2: You need to install the 2 packages babili-webpack-plugin and extract-text-webpack-plugin
In the file webpack.config.js:
// define these variables before "module.exports"
var BabiliPlugin = require('babili-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {...};
Then, setting the pluggin options:
plugins: [
new BabiliPlugin({}, { test: /\.js$/, comments: false }),
new ExtractTextPlugin('[name]'),
... and other options
]
and the output options:
output: {
filename: '[name]',
... and other options
}
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/*'}
])
]
};