I am trying to use Module Dynamic Import to create a bundle with an npm package using this is an excellent tutorial: https://webpack.js.org/guides/code-splitting/
But the npm package that I want to load dynamically has its own chunk dependencies:
npm package chunk dependencies
I can see that Webpack created correctly the vendor chunk:
files generated
But the npm package to import 's chunks are not re-imported, so it fails:
the error
I googled a lot but I couldn't find much information about it and, I don't know if it is a bug, misconfiguration or it is not possible.
CONFIG:
// my-project/index.js
const initializeLiveAR = await import(/* webpackChunkName: */ 'revieve-livear-module'); "livear_[index]"
// webpack.config.js
module.exports = {
entry: {
'revieve-sdk': path.resolve(__dirname, config.main_entry),
demoAR: path.resolve(__dirname, config.demoAR),
demoPR: path.resolve(__dirname, config.demoPR),
},
devtool: 'source-map',
mode: process.env.NODE_ENV,
output: {
path: path.resolve(__dirname, 'build'),
publicPath: '/',
filename: '[name].min.js',
chunkFilename: '[name].chunk.js',
libraryTarget: 'umd',
},
plugins: [
process.env.ANALYZEBUNDLE ? new BundleAnalyzerPlugin() : function() {},
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
}),
new CopyWebpackPlugin([
{ from: 'index.html', to: '.' },
{ from: 'test', to: './test' },
{ from: 'changelog.md', to: '.' },
]),
],
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.css$/,
use: [{ loader: 'style-loader' }, { loader: 'css-loader' }],
},
],
},
};
Related
I've been working on using ModuleFederation and have ran into an issue where if the remote webpack configuration had optimize.splitChunks.chunk = "all" then the host application would throw a loadScript exception. This could be a complete fundamental knowledge gap on my part why that wouldn't work. I haven't seen any documentation on not using that option along with Module Federation.
Has anyone had similar experiences or can tell me why it's a conflicting setting?
Thanks for your help!
remote webpack.config.js
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { ModuleFederationPlugin } = webpack.container;
module.exports = {
entry: "./index.js",
mode: "development",
devServer: {
contentBase: path.join(__dirname, "dist"),
port: 1338,
},
output: {
publicPath: "auto",
},
optimization: {
splitChunks: {
chunk: "all"
}
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: "babel-loader",
exclude: /node_modules/,
options: {
presets: ["#babel/preset-react"],
},
},
],
},
plugins: [
new ModuleFederationPlugin({
name: "comic",
filename: "remoteEntry.js",
exposes: {
"./XKCD": "./app.jsx",
},
shared: [
{
react: { singleton: true, eager: true },
"react-dom": { singleton: true, eager: true },
},
],
}),
new HtmlWebpackPlugin({
template: "./index.html",
}),
],
};
host webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack").container
.ModuleFederationPlugin;
const path = require("path");
module.exports = {
entry: "./index.js",
mode: "development",
devServer: {
contentBase: path.join(__dirname, "dist"),
port: 1337,
},
output: {
publicPath: "auto",
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: "babel-loader",
exclude: /node_modules/,
options: {
presets: ["#babel/preset-react"],
},
},
],
},
plugins: [
new ModuleFederationPlugin({
name: "home",
filename: "remoteEntry.js",
remotes: {
comic: `comic#http://localhost:1338/remoteEntry.js)`,
},
shared: [
{
react: { singleton: true, eager: true },
"react-dom": { singleton: true, eager: true },
},
],
}),
new HtmlWebpackPlugin({
template: "./index.html",
}),
],
};
I have a similar problem.
I change the remote webpack.config.js optimization.splitChunks as
optimization: {
splitChunks: {
chunks: 'async'
}
}
This problem is fixed.
Maybe you can try it.
Sorry my pool english
I am getting this error when I run the app:
ERROR in ./node_modules/primereact/resources/themes/saga-blue/theme.css (./node_modules/css-loader!./node_modules/style-loader!./node_modules/css-loader!./node_modules/primereact/resources/themes/saga-blue/theme.css)
Module build failed (from ./node_modules/css-loader/index.js):
Unknown word (2:1)
1 |
> 2 | var content = require("!!../../../../css-loader/index.js!./theme.css");
| ^
3 |
4 | if(typeof content === 'string') content = [[module.id, content, '']];
5 |
# ./node_modules/primereact/resources/themes/saga-blue/theme.css 2:14-136 21:1-42:3 22:19-141
# ./src/index.js
I have not modified any of the common, dev and prod webpacks. I've read the other 2 questions posted around this but none of the answers worked.
I'll post the webpack configurations for your convenience.
Common:
const path = require('path');
const HtmlWebPackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
main: path.resolve(__dirname, "../src", "index.js"),
},
output: {
filename: '[name].[hash].js',
path: path.resolve(__dirname, '../dist'),
publicPath: "/"
},
devServer: {
port: 3042,
historyApiFallback: true,
overlay: true,
open: true,
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: [/node_modules/],
use: [{ loader: "babel-loader" }]
},
{
test: /.*\.(gif|png|jp(e*)g|svg)$/i,
use: [
{
loader: "url-loader",
options: {
limit: 21000,
name: "images/[name]_[hash:7].[ext]"
}
}
]
},
// Vendor CSS loader
// This is necessary to pack third party libraries like antd
{
test: /\.css$/,
include: path.resolve(__dirname, '../node_modules'),
use: [
'style-loader',
'css-loader'
],
},
]
},
plugins: [
new HtmlWebPackPlugin({
template: path.resolve(__dirname, '../public', 'index.html'),
}),
],
resolve: {
extensions: ['.js', '.jsx']
},
}
Dev:
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const mapStyle = process.env.MAP_STYLE === 'true';
module.exports = merge (common, {
mode: 'development',
devtool: 'inline-source-map',
devServer: {
port: 3042,
historyApiFallback: true,
overlay: true,
open: true,
stats: 'errors-only'
},
module: {
rules: [
{
test: /\.css$/,
use: [
{ loader: "style-loader" },
{ loader: mapStyle ? "css-loader?sourceMap" : "css-loader" }
]
},
{
test: /\.s(a|c)ss$/,
use: [
{ loader: "style-loader" },
{ loader: "css-loader" },
{ loader: "sass-loader" }
]
},
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
}),
],
});
Prod:
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const ManifestPlugin = require('webpack-manifest-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const enableBundleAnalyzer = process.env.ENABLE_ANALYZER === 'true';
module.exports = merge(common, {
mode: 'production',
devtool: 'source-map',
module: {
rules: [
{
test: /\.css$/,
use: [
{ loader: MiniCssExtractPlugin.loader },
{ loader: "css-loader" }
]
},
{
test: /\.s(a|c)ss$/,
use: [
{ loader: MiniCssExtractPlugin.loader },
{ loader: "css-loader" },
{ loader: "sass-loader" }
]
},
]
},
optimization: {
splitChunks: {
chunks: 'all',
},
runtimeChunk: false,
},
plugins: [
new CleanWebpackPlugin([path.resolve(__dirname, '../dist')], {
root: process.cwd(),
verbose: true,
dry: false
}),
new OptimizeCssAssetsPlugin(),
new MiniCssExtractPlugin({
filename: "[name].[hash:8].css",
chunkFilename: "[id].[hash:8].css"
}),
new ManifestPlugin(),
new BundleAnalyzerPlugin({
analyzerMode: enableBundleAnalyzer === true ? 'static' : 'disabled',
openAnalyzer: true,
}),
],
});
And here is where I import them:
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import App from './components/App';
import store from './app/store';
import './assets/styles/style.sass';
import './assets/styles/style.css';
import './index.scss';
import 'primereact/resources/primereact.min.css';
import 'primeicons/primeicons.css';
import 'primeflex/primeflex.css';
import 'primereact/resources/themes/saga-blue/theme.css';
import '/src/assets/styles/customTheme.scss';
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
// Check if hot reloading is enable. If it is, changes won't reload the page.
// This is related to webpack-dev-server and works on development only.
if (module.hot) {
module.hot.accept();
}
One of the questions answered this by saying that i needed the url-loader but, as you can see, the boilerplate contains that aswell.
I hope I gave you enough information. Thank you in advance.
I think I've found my answer. I needed to exclude node_modules from the css loader rules from both the dev and prod configurations since the common configuration was handling that. The error was thrown because there were 2 conflicting css loaders.
I want to have some dependencies in different chunks so client.js would be smaller. webpack 4.16.5
Why I get same code included to several chunks? What's missing?
const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
mode: 'production',
target: 'web',
// devtool: 'source-map',
entry: {
echarts: ['echarts'],
vendor_1: ['react', 'immutable', 'lodash', 'redux', 'redux-saga'],
vendor_2: ['#material-ui/core', '#tinymce/tinymce-react'],
client: ['babel-polyfill', path.join(__dirname, 'app/index.js')],
},
output: {
path: path.join(__dirname, '/dist/'),
filename: '[hash].[name].js',
publicPath: './',
},
resolve: {
modules: [
path.join(__dirname, '/app'),
'node_modules',
],
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
template: 'app/index.tpl.html',
inject: 'body',
filename: 'index.html',
}),
new BundleAnalyzerPlugin(),
],
module: {
rules: [
{
test: /\.js?$/,
exclude: /node_modules/,
use: [{
loader: 'babel-loader',
}],
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader?modules&localIdentName=[name]---[local]---[hash:base64:5]',
'sass-loader',
],
},
{
test: /\.woff(2)?(\?[a-z0-9#=&.]+)?$/,
use: [{
loader: 'url?limit=10000&mimetype=application/font-woff',
}],
},
{
test: /\.(ttf|eot|svg)(\?[a-z0-9#=&.]+)?$/,
use: [{
loader: 'file',
}],
},
],
},
};
I added optimization config and it works now as expected.
optimization: {
splitChunks: {
chunks: 'initial',
},
},
I've played with values a bit and this was the best result for my code base without any extra code edits. You can find all possible options here:
https://webpack.js.org/configuration/optimization/
Thanks Pavel for the tip ;)
I'm trying to deploy my VueJS Django app to Heroku but running into issues with running webpack on Heroku. I'm able to collect the static files but it doesn't seem like webpack is running (webpack not found) so the website isn't running webpack, which means not only will VueJs files not be transpiled to ES5, but my index.html page will not even call the bundled up code that webpack outputs. Any ideas why this is happening and how to fix it?
On somewhat related notes: I'm using Gunicorn as web server and whitenoise to serve my static files.
Also, once I am able to run webpack, how do I get ride of this error in the console even though I have put es2015 preset in my .babelrc
vendor.js:1 Uncaught SyntaxError: Unexpected token import
import Vue from 'vue'
import ElementUI from 'element-ui'
Here's what I have (mostly everything is based off of VueJS Element starter kit)
Package.json:
{
"name": "element-starter",
"description": "A Vue.js project",
"author": "yi.shyang#ele.me",
"private": true,
"scripts": {
"dev": "webpack-dev-server -d --inline --hot --env.dev",
"heroku-postbuild": "rimraf static && webpack -p --config ./webpack.config.js --progress"
},
"dependencies": {
"element-ui": "^1.1.2",
"vue": "^2.1.8"
},
"engines": {
"node": ">=6"
},
"devDependencies": {
"autoprefixer": "^6.6.0",
"babel-core": "^6.21.0",
"babel-eslint": "^7.1.1",
"babel-loader": "^6.4.0",
"babel-plugin-transform-es2015-modules-commonjs": "^6.24.1",
"babel-preset-es2015": "^6.13.2",
"css-loader": "^0.27.0",
"eslint": "^3.12.2",
"eslint-config-enough": "^0.2.2",
"eslint-loader": "^1.6.3",
"file-loader": "^0.10.1",
"html-loader": "^0.4.5",
"html-webpack-plugin": "^2.24.1",
"postcss-loader": "^1.3.3",
"rimraf": "^2.5.4",
"style-loader": "^0.13.2",
"url-loader": "^0.5.8",
"vue-loader": "^11.1.4",
"vue-template-compiler": "^2.1.8",
"webpack": "^2.4.1",
"webpack-dev-server": "^2.4.2"
}
}
Procfile:
web: ./manage.py collectstatic --noinput; npm install; npm run heroku-postbuild; gunicorn dashboard.wsgi --log-file -
.babelrc:
{
"presets": [
["es2015", { "modules": false }]
]
}
webpack.config.js
const {
resolve
} = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const url = require('url')
// where the static files will be accessed from publicly
const publicPath = '/static/'
module.exports = (options = {}) => ({
entry: {
vendor: './src/vendor',
index: './src/main.js'
},
output: {
path: resolve(__dirname, 'static'),
filename: options.dev ? '[name].js' : '[name].js?[chunkhash]',
chunkFilename: '[id].js?[chunkhash]',
publicPath: options.dev ? '/assets/' : publicPath
},
module: {
rules: [{
test: /\.vue$/,
use: ['vue-loader']
},
{
test: /\.js$/,
use: ['babel-loader'],
include: [resolve(__dirname, 'src'), resolve(__dirname, 'static')],
exclude: /node_modules/
},
{
test: /\.html$/,
use: [{
loader: 'html-loader',
options: {
root: resolve(__dirname, 'src'),
attrs: ['img:src', 'link:href']
}
}]
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader', 'postcss-loader']
},
{
test: /favicon\.png$/,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}]
},
{
test: /\.(png|jpg|jpeg|gif|eot|ttf|woff|woff2|svg|svgz)(\?.+)?$/,
exclude: /favicon\.png$/,
use: [{
loader: 'url-loader',
options: {
limit: 10000
}
}]
}
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
names: ['vendor', 'manifest']
}),
new HtmlWebpackPlugin({
template: 'src/index.html',
chunksSortMode: 'dependency'
})
// options:dev ? '' : new webpack.DefinePlugin({
// 'process.env': {
// NODE_ENV: '"production"'
// }
// }),
// options:dev ? '' : new webpack.optimize.UglifyJsPlugin({
// compress: {
// warnings: false
// }
// })
],
resolve: {
alias: {
'~': resolve(__dirname, 'src')
}
},
devServer: {
host: '127.0.0.1',
port: 8010,
proxy: {
'/api/': {
target: 'http://127.0.0.1:8080',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
},
historyApiFallback: {
index: url.parse(options.dev ? '/assets/' : publicPath).pathname
}
},
devtool: options.dev ? '#eval-source-map' : '#source-map'
})
I'm not sure why my front end isn't running in hot mode. I am trying to decouple the front end and backend as much as possible. The only thing that connects the two is that I use django's webpack_loader app to load the webpack build to load into a template (index.html).
My backend is in Django and it is currently running on http://127.0.0.1:8000/.
My frontend is hosted on localhost:8080
My devServer for hot mode is on 0.0.0.0:8080
I tried changing a bit of my front end and saving it to see what would happen and nothing on the front end has been updated. In my developer tools I see this:
[HMR] Update check failed: SyntaxError: Unexpected token <
at Object.parse (native)
at XMLHttpRequest.request.onreadystatechange (http://localhost:8000/static/js/main.js:44:33)
Here are my npm scripts:
"scripts": {
"watch-client": "node ./node_modules/webpack/bin/webpack.js --verbose --colors --display-error-details --config webpack.watch.js && node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js --config webpack.watch.js",
"watch": "npm run watch-client"
},
webpack.config.js:
var path = require('path')
var webpack = require('webpack');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
entry: [
'./app/index.js'
],
output: {
path: path.resolve(__dirname, 'public'),
publicPath: '/js/',
filename: 'main.js'
},
devtool: 'eval',
debug: true,
module: {
loaders: [
{ test: /\.json$/, loader: 'json-loader' },
{ test: /\.jsx$/, loader: 'jsx-loader' },
{ test: /\.es6$/, exclude: /node_modules/, loader: 'babel-loader?stage=0&optional=runtime'},
{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader?stage=0&optional=runtime'},
{ test: /\.less$/, exclude: /node_modules/, loader: ExtractTextPlugin.extract("style-loader", "css-loader")},
{ test: /\.css$/, exclude: /node_modules/, loader: 'style-loader!css-loader' }
]
},
plugins: [
new ExtractTextPlugin('style.css', {
allChunks: true
}),
new webpack.optimize.CommonsChunkPlugin('common.js'),
]
};
webpack.watch.js:
var Webpack = require("webpack");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var config = require("./webpack.config.js");
var BundleTracker = require('webpack-bundle-tracker');
var port = process.env.WEBPACK_PORT || 8080;
var host = process.env.HOST || 'localhost';
// add hot loader
config.entry.unshift(
"webpack-dev-server/client?http://" + host + ":" + port,
"webpack/hot/only-dev-server" // only prevents reload on syntax errors
);
config.plugins = [
new ExtractTextPlugin("style.css", {
allChunks: true
}),
new Webpack.HotModuleReplacementPlugin(),
new BundleTracker({filename: './webpack-stats.json'})
];
config.module.loaders = [
{ test: /\.json$/, loader: 'json-loader' },
{ test: /\.jsx$/, loader: 'jsx-loader' },
{ test: /\.es6$/, exclude: /node_modules/, loader: 'babel-loader?stage=0&optional=runtime'},
{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader?stage=0&optional=runtime'},
{ test: /\.less$/, exclude: /node_modules/, loader: ExtractTextPlugin.extract("style-loader", "css-loader")},
{ test: /\.css$/, exclude: /node_modules/, loader: 'style-loader!css-loader' }
];
// dev server for react hot loader
config.devServer = {
publicPath: "/js/",
filename: 'main.js',
contentBase: "./public",
hot: true,
inline: true,
lazy: false,
quiet: true,
noInfo: true,
headers: {"Access-Control-Allow-Origin": "*"},
stats: {colors: true},
host: "0.0.0.0",
port: port
};
module.exports = config;