Webpack with Thridparty bundle - javascript

i want to provide a webpack bundle which contains all common thirdparty vendors(angular 1.4, jQuery, and some other libs).
Currently the follow modules are developed
Module A
Vendor Module
Vendor Module:
Create a simple module with all thridparty libs(angular 1.4, jQuery, and some other libs)
webpack.config.js:
var webpack = require('webpack');
var path = require('path');
module.exports = {
entry: {
vendor: './index.js',
},
output: {
// filename: '[chunkhash].[name].js',
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
plugins: []
}
index.js:
require('jquery');
require('angular');
Module A:
index.js:
var angular = require('angular');
var myJQ = require('jQuery');
var app = angular.module("Test", []);
console.log("Angular Boostrap");
console.log(app);
console.log("jQuery Boostrap");
console.log(myJQ);
webpack.config.js:
var webpack = require('webpack');
var path = require('path');
module.exports = {
entry: {
main: './index.js',
},
externals: {
angular: 'angular',
"jQuery": {
root: '$',
commonjs: 'jquery',
amd: 'jquery'
}
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
plugins: []
}
Module A index.js can require 'angular' and i see the right output, but the require from 'jquery' failed with an error.
There a two questions in my mind.
Which is common way to include third party vendors?
Whats wrong with jquery in the Module A index.js
Thank you.

The best way to include third party vendors is the DllPlugin. It does exactly what you want, splitting your app in two bundles. That way the build process is fast, independent and you have no limits in your app, because the dllPlugin connects both bundles. Sadly, there is no documentation about the dllPlugin in the webpack v2 documentation yet, but there are tutorials around, like https://robertknight.me.uk/posts/webpack-dll-plugins/
I think it depends on which jQuery you use. If jQuery exposes itself onto the window automatically, try
externals: { jQuery: 'window.jQuery' }

Related

Webpack static field

why doesn't webpack support static field?
When i try
export class Game {
#lasttime = 0;
#FRAME_DURATION = 1000 / 144;
I get an error
Module parse failed: Unexpected character '#' (2:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders.
What is the problem?
const path = require('path');
const HTMLPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'js/main.js',
path: path.resolve(__dirname, 'dist'),
},
devtool: 'inline-source-map',
devServer: {
contentBase: './dist',
},
plugins: [
new HTMLPlugin({
template: './src/index.html'
})
],
};
https://webpack.js.org/guides/getting-started/#modules:
Note that webpack will not alter any code other than import and export statements. If you are using other ES2015 features, make sure to use a transpiler such as Babel or Bublé via webpack's loader system.
You need to configure babel-loader yourself, see https://webpack.js.org/loaders/babel-loader/#root

Functions are not available in webpack bundle

I'm working on Arrow project and I'm in phase to create the Bundle file using Webpack.
I grouped my modules in a folder. and for each folder I have index.js where I export all modules.
Also, I have global index.js that imports all index.js like this :
import * as Has from "./scripts/array/has"
import * as Math from "./scripts/array/math"
import * as Arrow from "./scripts/array"
export { Has, Math, Arrow }
Now, I want to create my bundle from this global index.js .
My Webpack configuration looks like :
const path = require("path")
const { CleanWebpackPlugin } = require("clean-webpack-plugin")
module.exports = {
mode: "development",
entry: {
arrow: "./src/1.x.x/index",
},
plugins: [
new CleanWebpackPlugin({ cleanStaleWebpackAssets: false }),
],
devtool: 'inline-source-map',
devServer: {
contentBase: './build',
},
output: {
filename: "[name]-alpha.js",
path: path.resolve(__dirname, 'build'),
},
optimization: {
splitChunks: {
chunks: 'all',
},
},
}
The Issue is when I try to import my functions from the build the functions do not appear in the Autocomplete and I received errors that these functions are undefined!
I have just ___esModule :
import { __esModule } from "./arrow-alpha"
I want to let developers use and import the functions like the example
import {omit} from "arrow" // arrow is the bundled file
const frameworks = ["react", "vue", "ember", "angular"];
const withoutAngular = omit(frameworks,"angular");
console.log(withoutAngular); // ["react", "vue", "ember"]
I blocked in this step for days and I could not figure out the issue.
It sounds like you are looking to export your code as library with webpack. In order to do so, you should export your library module as umd which can work for backend/client side so IDE can also understand what you export. Just add following configuration in your webpack.config.js:
output: {
libraryTarget: 'umd', // style for your library
library: 'yourLibName', // if you keen to have a name for library
// ...
},
NOTE: this only works if you pass to webpack a cjs style code, otherwise it will convert to harmony module which you can't export accordingly (such as esm module)
In order to make sure babel would convert your esm module to commonjs, you have to set modules to commonjs like this:
babel.config.js or .babelrc
[
"#babel/preset-env",
{
"modules": "commonjs",
}
]
Adding below Configuration. Will eject your final bundle to be accessed as Window.Arrow on adding script to index.html page
output: {
filename: "[name]-alpha.js",
path: path.resolve(__dirname, 'build'),
library: 'Arrow',
libraryTarget: 'var'
},
and your index.js page inside src folder to be as
module.exports = require('./scripts/array');

Webpack DllPlugin with gulp: Cannot find module '... vendor-manifest.json'

I have a rather large React application built with webpack 2. The application is embedded into a Drupal site as a SPA within the existing site. The Drupal site has a complex gulp build setup and I can't replicate it with webpack, so I decided to keep it.
I have split my React application into multiple parts using the DllPlugin / DllReferencePlugin combo which is shipped out of the box in webpack 2. This works great, and I get a nice vendor-bundle when building with webpack.
The problem is when I try to run my webpack configuration in gulp, I get an error. I might be doing it wrong, as I have not been able to find much documentation on this approach, but nevertheless, it's not working for me.
It looks like it's trying to include the the manifest file from my vendor-bundle before creating it.
Whenever I run one of my defined gulp tasks, like gulp react-vendor I get an error, saying that it cannot resolve the vendor-manifest.json file.
If I on other hand run webpack --config=webpack.dll.js in my terminal, webpack compiles just fine and with no errors.
I have included what I think is the relevant files. Any help on this is appreciated.
webpack.config.js
// Use node.js built-in path module to avoid path issues across platforms.
const path = require('path');
const webpack = require('webpack');
// Set environment variable.
const production = process.env.NODE_ENV === "production";
const appSource = path.join(__dirname, 'react/src/');
const buildPath = path.join(__dirname, 'react/build/');
const ReactConfig = {
entry: [
'./react/src/index.jsx'
],
output: {
path: buildPath,
publicPath: buildPath,
filename: 'app.js'
},
module: {
rules: [
{
exclude: /(node_modules)/,
use: {
loader: "babel-loader?cacheDirectory=true",
options: {
presets: ["react", "es2015", "stage-0"]
},
},
},
],
},
resolve: {
modules: [
path.join(__dirname, 'node_modules'),
'./react/src/'
],
extensions: ['.js', '.jsx', '.es6'],
},
context: __dirname,
devServer: {
historyApiFallback: true,
contentBase: appSource
},
// TODO: Split plugins based on prod and dev builds.
plugins: [
new webpack.DllReferencePlugin({
context: path.join(__dirname, "react", "src"),
manifest: require(path.join(__dirname, "react", "vendors", "vendor-manifest.json"))
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
filename: 'webpack-loader.js'
}),
]
};
// Add environment specific configuration.
if (production) {
ReactConfig.plugins.push(
new webpack.optimize.UglifyJsPlugin()
);
}
module.exports = [ReactConfig];
webpack.dll.js
const path = require("path");
const webpack = require("webpack");
const production = process.env.NODE_ENV === "production";
const DllConfig = {
entry: {
vendor: [path.join(__dirname, "react", "vendors", "vendors.js")]
},
output: {
path: path.join(__dirname, "react", "vendors"),
filename: "dll.[name].js",
library: "[name]"
},
plugins: [
new webpack.DllPlugin({
path: path.join(__dirname, "react", "vendors", "[name]-manifest.json"),
name: "[name]",
context: path.resolve(__dirname, "react", "src")
}),
// Resolve warning message related to the 'fetch' node_module.
new webpack.IgnorePlugin(/\/iconv-loader$/),
],
resolve: {
modules: [
path.join(__dirname, 'node_modules'),
],
extensions: ['.js', '.jsx', '.es6'],
},
// Added to resolve a dependency issue in this build #https://github.com/hapijs/joi/issues/665
node: {
net: 'empty',
tls: 'empty',
dns: 'empty'
}
};
if (production) {
DllConfig.plugins.push(
new webpack.optimize.UglifyJsPlugin()
);
}
module.exports = [DllConfig];
vendors.js (to determine what to add to the Dll)
require("react");
require("react-bootstrap");
require("react-dom");
require("react-redux");
require("react-router-dom");
require("redux");
require("redux-form");
require("redux-promise");
require("redux-thunk");
require("classnames");
require("whatwg-fetch");
require("fetch");
require("prop-types");
require("url");
require("validator");
gulpfile.js
'use strict';
const gulp = require('gulp');
const webpack = require ('webpack');
const reactConfig = require('./webpack.config.js');
const vendorConfig = require('./webpack.dll.js');
// React webpack source build.
gulp.task('react-src', function (callback) {
webpack(reactConfig, function (err, stats) {
callback();
})
});
// React webpack vendor build.
gulp.task('react-vendor', function (callback) {
webpack(vendorConfig, function (err, stats) {
callback();
})
});
// Full webpack react build.
gulp.task('react-full', ['react-vendor', 'react-src']);
NOTE:
If I build my vendor-bundle with the terminal with webpack --config=webpack.dll.js first and it creates the vendor-manifest.json file, I can then subsequently successfully run my gulp tasks with no issues.
This is not very helpful though, as this still will not allow me to use webpack with gulp, as I intend to clean the build before new builds run.
I ended up using the solution mentioned in the end of my question. I build my DLL file first and then I can successfully run my gulp webpack tasks.
One change that can make it easier to debug the issue, is to use the Gulp utility module (gulp-util) to show any webpack errors that might show up during build of webpack, using gulp.
My final gulp setup ended up looking like this:
gulpfile.js
'use strict';
const gulp = require('gulp');
const gutil = require('gulp-util');
const webpack = require('webpack');
const reactConfig = require('./webpack.config.js');
const vendorConfig = require('./webpack.dll.js');
// React webpack source build.
gulp.task('react', function (callback) {
webpack(reactConfig, function (err, stats) {
if (err) {
throw new gutil.PluginError('webpack', err);
}
else {
gutil.log('[webpack]', stats.toString());
}
callback();
});
});
// React webpack vendor build.
gulp.task('react-vendor', function (callback) {
webpack(vendorConfig, function (err, stats) {
if (err) {
throw new gutil.PluginError('webpack', err);
}
else {
gutil.log('[webpack]', stats.toString());
}
callback();
});
});
// React: Rebuilds both source and vendor in the right order.
gulp.task('react-full', ['react-vendor'], function () {
gulp.start('react');
});
I hope this might help someone in a similar situation.
Whenever I run one of my defined gulp tasks, like gulp react-vendor I get an error, saying that it cannot resolve the vendor-manifest.json file.
Your gulpfile.js contains this:
const reactConfig = require('./webpack.config.js');
const vendorConfig = require('./webpack.dll.js');
And webpack.config.js contains this:
new webpack.DllReferencePlugin({
context: path.join(__dirname, "react", "src"),
manifest: require(path.join(__dirname, "react", "vendors", "vendor-manifest.json"))
}),
The require() calls are currently all executed immediately. Whenever you run Gulp, it will evaluate both Webpack configuration files. As currently configured, Node runs the code in webpack.config.js at startup, and from there it sees the require() used in your creation of the DllReferencePlugin, so it will also try to read manifest.json at that time and turn it into an object...which is before it has been built.
You can solve this in one of two ways:
The DllReferencePlugin's manifest option supports either an object (which is what you are currently providing), or else a string containing the path of the manifest file. In other words, it should work if you remove the require() from around your path.join(...) call.
Alternatively, you can also defer the loading of the Webpack config files. Moving your const reactConfig = require('./webpack.config.js'); from the top of the file directly into the gulp task function should be sufficient, assuming that this function is not invoked until after the manifest has been built.

Redundant Modules in Webpack Dllplugin

I am using Webpack 3.0.0 for my application. I am trying to split my references to libraries in to separate files using the DllPlugins in Webpack. Initially I was using CommonsChunkPlugin which allowed me to split my libraries as jquery.js and kendo.js . The kendo.js file did not contain the jquery library.
After I changed this using DllPlugin, it seems both jquery.js and kendo.js have jquery.
Below is my configuration
var webpack = require('webpack');
var path = require('path');
module.exports = {
entry: {
jquery: ["jquery"],
kendo: [
'kendo.autocomplete.min',
'kendo.treelist.min',
'kendo.slider.min',
'kendo.tooltip.min',
'kendo.dataviz.chart.min',
'kendo.dataviz.themes.min',
'kendo.grid.min',
'kendo.data.min',
'kendo.core.min'
]
},
output: {
filename: "[name].bundle.js",
path: path.resolve(__dirname, '../assets'),
library: "[name]_lib"
},
plugins: [
new webpack.DllPlugin({
path: path.resolve(__dirname, '../assets/[name]-manifest.json'),
name: '[name]_lib'
})
],
};
Could someone please help change the configuration to exclude jquery from kendo.js .

Optimal webpack.config with webpack 2 for AngularJS 1.x app?

I want to set up an Angular 1.x app from scratch using webpack 2.
I am having trouble finding the best configuration for webpack.config, with optimal entry and output for production (meaning, all code, style and templating minified and gziped with no code repetition).
My main problem is how to set up webpack.config so that it recognizes all partials within the folder structure of my project, like these:
My current config file, for reference (which can't see subfolders):
var HtmlWebpackPlugin = require( 'html-webpack-plugin' );
var ExtractTextPlugin = require( 'extract-text-webpack-plugin' );
var path = require( 'path' );
module.exports = {
devServer: {
compress: true,
contentBase: path.join( __dirname, '/dist' ),
open: true,
port: 9000,
stats: 'errors-only'
},
entry: './src/app.js',
output: {
path: path.join( __dirname, '/dist' ),
filename: 'app.bundle.js'
},
module: {
rules: [ {
test: /\.scss$/,
use: ExtractTextPlugin.extract( {
fallback: 'style-loader',
use: [
'css-loader',
'sass-loader'
],
publicPath: '/dist'
} )
} ]
},
plugins: [
new HtmlWebpackPlugin( {
hash: true,
minify: { collapseWhitespace: true },
template: './src/index.html',
title: 'Prov'
} ),
new ExtractTextPlugin( {
filename: 'main.css',
allChunks: true
} )
]
};
Note that this isn't an exhaustive solution, as there are many optimizations one can make in the frontend, and I've kept the code snippets fairly short.
With webpack, there are a few routes that you can take to include partials into your app.js.
Solution 1
You can import/require your partials within app.js as such:
app.js
var angular = require('angular');
var proverbList = require('./proverb/list/proverb.list');
// require other components
// set up your app as normal
This allows the app.bundle.js to include your component js files in the main bundle. You can also use html-loader to include templates in the final bundle.
This isn't ideal, as all it does is create a large bundle.js (which doesn't leverage multiple downloads with http2 nor does it allow loading of components/files when the user explicitly requires it).
Solution 2
Importing partials as separate entry files into your webpack bundle:
webpack.config.js
const globby = require('globby');
const sourceDir = 'src';
var webpackentry = {
app: `${__dirname}/src/app.js`
};
const glob = globby.sync(`${__dirname}/${sourceDir}/**/*.js`)
.map((file)=>{
let name = file.split('/').pop().replace('.js', '');
webpackentry[name] = file;
});
const config = {
entry: webpackentry,
...
}
The second solution is unorthodox but it can be useful if you wanted to split all your partials as <script> tags in your html (for example if your company/team uses that as a means to include your directive/components/controllers), or if you have an app-2.bundle.js.
Solution 3
Use CommonsChunkPlugin:
webpack.config.js
let webpackentry = {
vendor: [
'module1',
'module2',
'module3',
]
}
...
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: ['vendor'] //... add other modules
})
]
CommonsChunkPlugin allows webpack to scrawl through your entry files and discern common modules that are shared among them. This means that even if you are importing module1 in different files, they will be compiled only once in your final bundle.

Categories

Resources