I've been trying to provide my webpack compiled modules with grunt. All my files need at least 1 or 2 globals (React, Backbone and underscore).
These assets will be compiled into js, react views. I'm wondering how I can use ProvidePlugin to give all my modules some base packages, with webpack and/or grunt configs?
I have no clue where this code would live! Gruntfile.js? Entry js file?
plugins: [
webpack.ProvidePlugin({
"_": "underscore"
})
]
or
new webpack.ProvidePlugin({
$: "jquery"
})
I researched and found this is the closest:
Webpack ProvidePlugin vs externals?
Thank you very much for your help!
Figured it out! Ends up the grunt webpack config takes the same options? Looks like it :)
grunt.initConfig({
pkg: pkgConfig,
loyalty: loyaltyConfig,
webpack: {
development: {
// resolve: {
// modulesDirectories: [ 'vendors' ]
// },
amd: {
$: true
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
_: 'underscore',
React: 'react/addons',
config: 'json!../../config.json'
})
],
This will include the required elements if and only if they're used apparently.
Related
From webpack documentation I found, that plugins can be connected either with plugins field
module.exports = {
...
plugins: [
new webpack.ProgressPlugin(),
new HtmlWebpackPlugin({ template: './src/index.html' }),
],
...
};
or in resolve.plugins:
...
var DirectoryNamedWebpackPlugin = require("directory-named-webpack-plugin");
resolve: {
plugins: [
new DirectoryNamedWebpackPlugin()
]
}
...
What is the difference between between these plugins, so they have to be connected differently?
The difference between resolve.plugins and plugins is that the plugins configured in resolve.plugins work within the module's resolution rules. plugins are configured to extend webpack and are combined with loaders for maximum control
resolve.plugins
Plugins
I know its simple but with update of rails 6. there is new syntax in rails 6 for manage javascript assets which is maintained by webpacker.
//application.js
require("#rails/ujs") //.start()
require("turbolinks").start()
require("#rails/activestorage").start()
require('jquery').start()
require('jquery_ujs').start()
require('bootstrap-daterangepicker').start()
require("custom/custom").start()
require("bootstrap").start()
require("channels")
i am able to add custom/custom but bootstrap and jquery is not working
i have install jquery and bootstrap via npm
run below command to add jQuery.
$ yarn add jquery
Add below code in config/webpack/environment.js
const webpack = require('webpack')
environment.plugins.prepend('Provide',
new webpack.ProvidePlugin({
$: 'jquery/src/jquery',
jQuery: 'jquery/src/jquery'
})
)
Require jquery in application.js file.
require('jquery')
No more need to add jquery-rails gem!
to resolve jquery third party plugin issue add jquery via yarn
yarn add jquery
for adding jquery support in rails 6 application first we need to add below configuration
# app/config/webpack/environment.js
const {environment} = require('#rails/webpacker');
const webpack = require('webpack');
environment.plugins.append('Provide', new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery' # or if its not work specify path `'jquery/src/jquery'` which node_modules path for jquery
}));
module.exports = environment;
for import any jquery related plugin in app/javascripts/packs/application.js
use below instructions
import 'bootstrap/dist/js/bootstrap';
import 'bootstrap-daterangepicker/daterangepicker'
updated with expose-loader for jQuery
yarn add expose-loader
Then add this to config/webpack/environment.js
environment.loaders.append('jquery', {
test: require.resolve('jquery'),
use: [{
loader: 'expose-loader',
options: '$',
}, {
loader: 'expose-loader',
options: 'jQuery',
}],
});
module.exports = environment;
Apparently expose-loader 1.0.0 has a different format:
environment.loaders.append('jquery', {
test: require.resolve('jquery'),
rules: [
{
loader: 'expose-loader',
options: {
exposes: ['$', 'jQuery'],
},
},
],
});
Ensure you have yarn installed and updated to the latest version, then create your rails application.
First Run the following command to install Bootstrap, Jquery and Popper.js
yarn add bootstrap#4.5 jquery popper.js
On the above ofcourse you can change to the latest version of Bootstrap.
If you open package.json file, you will notice Bootstrap 4.5, Jquery latest version and Popper.js latest versions have been added for you.
Next go to config/webpack/environment.js and amend the file.
const { environment } = require('#rails/webpacker')
const webpack = require("webpack")
environment.plugins.append("Provide", new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
Popper: ['popper.js', 'default']
}))
module.exports = environment
Next go to app/assets/stylesheets/application.css and amend the file make sure to require bootstrap.
*= require bootstrap
*= require_tree .
*= require_self
Finally go to application.js file and amend the file by adding import 'bootstrap'; in order for bootstrap javascript to work.
import 'bootstrap';
require("#rails/ujs").start()
require("turbolinks").start()
require("#rails/activestorage").start()
Save all changes, restart rails server.
That should work.
In webpacker v. 6 there is no config/webpack/environment.js and other files structure
Firstly you need add JQuery to your project using yarn:
yarn add jquery
After that you can integrate JQuery using one of ways:
Directly update base config:
// config/webpack/base.js
const { webpackConfig } = require('#rails/webpacker')
const webpack = require('webpack')
webpackConfig.
plugins.
push(
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})
)
module.exports = webpackConfig
Use custom config and merge it to base config:
// config/webpack/base.js
const { webpackConfig, merge } = require('#rails/webpacker')
const customConfig = require('./custom')
module.exports = merge(webpackConfig, customConfig)
// config/webpack/custom.js
const webpack = require('webpack')
module.exports = {
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})
]
}
On my opinion second way is more flexible
I use laravel-mix (including webpack) to bundle JS files.
Using BundleAnalyzerPlugin I found that my output file includes more than one copy of JQuery lib which boosts the output file size.
It seams several modules includes JQuery by themselves.
Any ideas how to avoid this and remove all redundant jquery inclusions?
(UPDATED with more info)
Image of Bundle analyzer output
webpack.mix.js
const { mix } = require('laravel-mix');
const webpack = require('webpack');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
mix.js('resources/assets/js/admin.js', 'public/js')
mix.webpackConfig({
plugins: [
new BundleAnalyzerPlugin(),
new webpack.ProvidePlugin({ // Added as a suggestion. Makes no difference
'$': 'jquery',
'jQuery': 'jquery',
'window.jQuery': 'jquery'
})
],
});
admin.js
import 'jquery'
import 'toastr'
import 'jquery' in your entry file and add the below block to your webpack.config
plugins: [
new webpack.ProvidePlugin({
'$': 'jquery',
'jQuery': 'jquery',
'window.jQuery': 'jquery'
})
]
Refer: Webpack Provide Plugin
I have defined webpack ProvidePlugin to load Backbone-relational library as follows.
plugins: [
new webpack.ProvidePlugin({
$ : "jquery",
Backbone : "backbone",
_ : "underscore",
"Backbone.Relational": "backbone-relational",
})
However Backbone-relational also exports:
Backbone.RelationalModel
Backbone.HasOne
Backbone.HasMany
etc...
My problem is that I can not have them all exported. What is the right way to do this with webpack?
Try to use relational shim as described here
I am trying to set up webpack production configuration. All looks well. However, I realized that while using the commons chunk plugin, it covers all the files in common as expected. What I want to do is, separation of common library modules and common application modules. My config file is :
module.exports = {
entry: {
lib: ["react", "react-dom"],
app: "./ui-v2/app/app.js",
app2: "./ui-v2/app/app2.js"
},
output: {
path: path.join(__dirname, "target/ui/v2"),
filename: "/app/[name].[chunkhash].min.js"
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.(png|jpg|svg)/,
loader: "file-loader?name=img/[name].[hash].[ext]"
// loaders: ["url", "image-webpack"]
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader!autoprefixer-loader!sass-loader", {
publicPath: __dirname
})
},
{
test: /\.(woff|woff2|ttf|eot)$/,
loader: "file-loader?name=fonts/[name].[hash].[ext]"
}
]
},
plugins: [
clean,
new webpack.optimize.CommonsChunkPlugin("common", "app/common.[chunkhash].js"),
new webpack.ProvidePlugin({
React: "react",
ReactDOM: "react-dom",
$: "jquery",
_: "lodash"
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
sourceMap: true
},
mangle: {
except: ["exports", "import", "$", "_", "require", "React", "ReactDOM"]
}
}),
new ExtractTextPlugin("styles/[name].[contenthash].css"),
new Manifest()
]
}
Basically I have 3 modules in the app; app.js, app2.js and a common component user.js.
What I want to achieve is to bundle all library related files like react, react-dom, lodash, etc in a lib bundle, and common application components like user.js in a common bundle. In order to do this, I thought there might be an option to exclude the files that I don't want them to go to "common" file. If I use this output, what is the point for long term caching files for library bundles because whenever I get a common component in my project, they will go into the common bundle and the content hash will be different, but nothing changes in this library files like react, jquery, lodash, etc.
Anyway, what I have at the end of build process is everything still goes into the common bundle and lib has nothing and the file sizes are :
app.<hash>.min.js -> 3.05KB
app2.<hash>.min.js -> 3.05KB
lib.<hash>.min.js -> 165 Bytes (has almost nothing!)
common.<hash>.js -> 678 KB
Is there any way to achieve what I want or what would be the best approach to a production build in similar cases? Thank you!
Its because the first parameter for CommonsChunkPlugin is "common" where it should be "lib". The plugin picks up the entry with a name matching with the value of its first parameter.
A simple example config picked from webpack's wiki -
var webpack = require("webpack");
module.exports = {
entry: {
app: "./app.js",
vendor: ["jquery", "underscore", ...],
},
output: {
filename: "bundle.js"
},
plugins: [
new webpack.optimize.CommonsChunkPlugin(/* chunkName= */"vendor", /* filename= */"vendor.bundle.js")
]
};
Note that the "vendor" entry is again specified in CommonsChunkPlugin
You should check out Webpack's DLL Plugin.
https://github.com/webpack/webpack/blob/cb3d8e2097503c7245c5dda5b7a6e9d63421a72b/examples/dll/README.md
With this plugin you bundle up common 3rd party vendor dependencies such as React and friends in a DLL, which is essentially just a JSON Manifest that goes along with your requires wrapped in webpack context and cached to disk.
In your project code, you would have your shared components which depend on React and friends, and you would have your application code which depend on your shared components as well as react and friends.
Your project would incorporate the DLL Reference plugin as you can see here:
https://github.com/webpack/webpack/blob/cb3d8e2097503c7245c5dda5b7a6e9d63421a72b/examples/dll-user/README.md
This will see to it that your shared components and your application code pull React and other 3rd party modules from the same DLL bundle. This can help improve build times and the performance of the dev server and hot module reloading.