I am building a project with webpack and I want to remove duplicated custom materialize.js library with the following config:
const path = require('path');
const webpack = require('webpack');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
entry: {
frontend: './src/AppBundle/Resources/js/Frontend/frontend.js',
panel: ['./src/AppBundle/Resources/js/Panel/forms.js', './src/AppBundle/Resources/js/Panel/vue/main.js']
},
output: {
filename: '[name].min.js',
path: path.join(__dirname, 'web/js')
},
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /node_modules|src\/AppBundle\/Resources\/js\/Vendor/,
name: 'vendor',
chunks: 'all'
}
}
}
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
loader: 'babel-loader'
},
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
]
}
]
},
resolve: {
extensions: ['*', '.js', '.vue', '.json']
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
'window.$': 'jquery',
'window.jQuery': 'jquery'
}),
new VueLoaderPlugin(),
new BundleAnalyzerPlugin()
]
};
Thus, I would like to get three files: frontend, panel and vendors (this one with vue.js, jquery.js and materialize.js)
Here is my source folder structure:
Frontend
|_frontend.js
Panel
|_forms.js
|_vue
|_(...).js
Vendor
|_materialize.js
In frontend.js and forms.js I have added jQuery:
window.$ = window.jQuery = require('jquery');
Bacause jQuery is taken from node_modules, it is appended using optimization.splitChunks in vendor.js
Unfortunately I need to have custom materialize.js file (modified, not form package in node_module), so I applied it in optimization.splitChunks, and add to previous two files as well:
require('../Vendor/materialize');
It works correctry, except it is appended twice in frontend.js and panel.js, not in vendor.js. I would to have it just in vendor.js.
BundleAnalyzerPlugin shows output like this:
I thought, I can add materialize.js as the vendor entry point (and get rid of require('../Vendor/materialize')
from previous two files), but unfortunately it doesn't work, i.e. materialize functions are not found, e.g. :
...
Uncaught TypeError: $(...).pickadate is not a function
...
In html I have scripts one after another:
<script type="text/javascript" src="/js/vendor.min.js"></script>
<script type="text/javascript" src="/js/frontend.min.js"></script>
It was working right without webpack, but now I don't know how to make it to working correctry?
I've already solved it. The problem was with regex. SplitChunksPlugin did not resolved it:
test: /node_modules|src\/AppBundle\/Resources\/js\/Vendor/,
In a case of having two directories of chunks, the best way out is to create two separate cache groups respectively for each directory and take advantage of path.resolve function:
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: path.resolve('node_modules'),
name: 'vendor',
chunks: 'all'
},
materialize: {
test: path.resolve('src/AppBundle/Resources/js/Vendor'),
name: 'vendor',
chunks: 'all'
}
}
}
},
Final output: