Using jquery-mobile with Webpack - javascript

I am trying to load jquery-mobile using webpack with no luck so far.
I am aware that jquery-mobile depends on jquery-ui which in turn depends on jquery.
How do I set up such a scenario in Webpack?
Here is my webpack.config.js:
var webpack = require('webpack');
var path = require('path');
var bower_dir = __dirname + '/bower_components';
module.exports = {
context: __dirname,
entry: './assets/js/index.js',
output: {
path: path.resolve('./assets/bundles/'),
filename: "[name]-[hash].js",
},
plugins: [
new BundleTracker({filename: './webpack-stats.json'}),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
})
],
module: {
loaders: [
{test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/, loader: "imports?this=>window"}
]
},
resolve: {
alias: {
'jquery': bower_dir + '/jquery/src/jquery.js',
'jquery-ui': bower_dir + '/jquery-ui/jquery-ui.js',
'jquery-mobile': bower_dir + '/jquery-mobile/js/jquery.mobile.js'
}
}
};
Any help would be much appreciated.
Thank you all in advance.

If you just add the scripts you need to the page in the correct order, you don't need to worry about that in webpack.
All you have to do is tell webpack that those modules are loaded from external references, like so:
{
externals: {
'jquery': 'jQuery'
}
}
This tells webpack that every time you require('jquery') it will return a globally available variable jQuery.

Related

Webpack dependent plugin

i am trying to add sammyjs on webpack as a plugin. But sammyjs is dependent on jquery and jquery is also present on plugin.
Here is the code
const webpack = require('webpack')
const jquery = require('jquery')
const Sammy = require('sammy')
const {resolve} = require('path')
const webpackConfig = {
entry: "./src/js/bootstrap.js",
output: {
path: resolve("dist"),
filename: "bundle.js",
publicPath: '/dist/'
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
Sammy: 'Sammy'
})
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
},
resolve: {
alias: {
graph: resolve(__dirname, 'src/modules/graph'),
}
},
};
module.exports = webpackConfig;
but building it. Sammyjs keeps asking for jQuery variable:
I dont just want to import it in pages because it feels like the bundle is getting bigger.
Please tell me if i am doing right. Or there is other way to attain clean and smaller bundle.

Webpack with Thridparty bundle

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' }

Automatically loading externals with Webpack

I've done some searching but was wondering if there's an elegant solution here. When building a Webpack app, it's common to have dependencies that don't need to be compiled/bundled, like jQuery, React, ReactDOM, Angular, or Bootstrap, to name a few. You can list these in your Webpack config file in an externals object, but externals just assumes that these libraries will be available as namespaced globals at runtime.
This means that for each entry in your externals hash, you also need to toss in a script tag in your HTML. This makes sense if you're referencing an external CDN, but I'm thinking this could be automated if all you want to do is copy some dist file from a library in node_modules.
I've been looking for examples of how to do this but I haven't seen any yet. I messed with external-loader but I haven't had any luck integrating it (the documentation doesn't seem to provide a complete example).
Essentially, this would need to happen:
Libraries that shouldn't be bundled should be added to resolve.alias, e.g. {"react": "react/dist/react.js"}
A loader copies the dist files to the public directory (maybe this could just be done with file-loader?)
An HTML loader or maybe plugin inserts the script tags before the bundle.js script tag
If something like this doesn't exist, I might look into trying to make one; I'm just posting this here to see if anyone might know of a pre-baked solution, as it seems like it'd be a common problem for building web apps and I figured I'm probably missing something.
var path = require("path");
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var helpers = require('./helpers');
var WebpackNotifierPlugin = require('webpack-notifier');
module.exports = {
entry: {
'index-ref': './app/index-ref.ts',
'vendor': './app/vendor.ts',
'app': './app/main.ts',
},
resolve: {
extensions: ['', '.ts', '.js']
},
module: {
loaders: [
{
test: /\.ts$/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader']
},
{
test: /\.html$/,
loader: 'html'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
loader: 'file?name=assets/[name].[hash].[ext]'
},
{
test: /\.css$/,
exclude: helpers.root('app'),
loader: ExtractTextPlugin.extract('style', 'css?sourceMap')
},
{
test: /\.css$/,
include: helpers.root('app'),
loader: 'raw'
}
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: ['app', 'vendor', 'index-ref']
}),
new HtmlWebpackPlugin({
filename: '../index.html',
template: 'template' + '/default.html',
lib: ['jQuery'],
chunks: ['entry-name']
}),
new HtmlWebpackExternalsPlugin([
// Using a CDN for a JS library
{
name: 'jquery',
var: 'jQuery',
url: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.js'
}
],
{
basedir: 'node_modules',
dest: 'lib'
}),
new WebpackNotifierPlugin()
]
};
Am I missing anything here?
I didn't find a pre-existing solution, so I wrote a plugin to supplement the HtmlWebpackPlugin. It takes an array of externals and appends script/link tags to the HTML file, generates the externals hash, and can use CDNs or local files.
https://github.com/mmiller42/html-webpack-externals-plugin
If you don't want to add extra package bloat then HtmlWebpackPlugin has templating features, so you could do something like this:
//template.html
<html>
<head>
<%= htmlWebpackPlugin.options.externals %>
</head>
...
</html>
and then something like this in your webpack config:
//webpack.config.js
const EXTERNALS = [
{
name: 'react',
globalVarName: 'React',
src: 'https://cdn.example.com/react#18',
},
...
]
module.exports = {
...,
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'template.html',
externals: EXTERNALS.reduce(
(scripts, external) => (
`${scripts}<script src="${external.src}"></script>`
), ''
)
})
],
externals: EXTERNALS.reduce(
(res, external) => ({
...res,
[external.name]: external.globalVarName,
}), {}
),
}
(You can obviously add any environment customisations/finer details/etc. you want in the webpack config file.)
EDIT:
For some extra panache you could also get the current package versions from your node_modules rather than hard-coding them into the webpack file:
const fs = require('fs')
function getPackageVersion(packageName) {
const pkgPath = `node_modules/${packageName}`
const pkg = JSON.parse(fs.readFileSync(`${pkgPath}/package.json`, 'utf8'))
return pkg['version']
}

webpack build less files output one css minify file

Is webpack the tool that I need to pass several less files into one minified CSS file?
if so, I'm not sure what I'm doing wrong in the code below?
Is there a way of outputting to different file paths, right now my js file outputs to './assets/javascripts/bundle/', I would like my css file to output to './assets/stylesheets/bundle/' , how would I do this?
Update
I did a test and I can build my less files to one css file but still can't find out how to set multiple paths for the output folder, now I have to comment out the js entry part and change output path...
webpack config
var path = require('path');
var webpack = require("webpack");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
entry: {
'MediaIndex':['./assets/javascripts/Media/Index/Base.js'],
// stylesheets
'MediaIndexStyleSheet':['./assets/stylesheets/Media/Index/Base.js']
},
output: {
path: './assets/javascripts/bundle/',
filename: '[name].js'
},
resolve: {
alias: {
jquery: path.join(__dirname, "assets/javascripts/lib/jquery-1.11.1.min.js"),
"jquery-ui": path.join(__dirname, "assets/javascripts/lib/jquery-ui.min.js"),
}
},
plugins: [
new webpack.ProvidePlugin({
jQuery: "jquery",
$: "jquery"
}),
new ExtractTextPlugin("[name].css")
],
module: {
loaders: [
{
test: /\.css$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader")
},
{
test: /\.less$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader!less-loader")
}
]
},
};
assets/stylesheets/Media/Index/Base.js
require('../../../Global/Config.less');
require('../../../Global/Fp.less');
require('../../../Global/Urb.less');
require('../../../Global/Ad1.less');
require('./Nav0.less');
require('./Index.less');
require('./Content.less');
Config.less
#color: 'red';
Index.less
body {
background-color: #{color};
}
You're almost there. Like you already did, you can get all your styling into one css file using ExtractTextPlugin. To put your js and css into a different directories, you can just define a path in ExtractTextPlugin or output.filename that is relative to your output.path. For example:
output: {
path: './assets',
filename: './javascripts/bundle/[name].js'
},
plugins: [
new ExtractTextPlugin("./stylesheets/bundle/[name].css")
]

How to require 'ace-builds/ace' with Webpack and noParse option

I'm currently trying to require ace-builds (installed from bower) with webpack. Since it's a huge lib, I'm adding the whole folder to noParse option. I'm running webpack with -d option on terminal.
The problem is: when my code tries to require it, it is an empty object. Also, it's not loaded by the browser. Here are some information of what I'm doing:
My file:
// custom_editor.js
// ace-builds are aliased by ace keyword
var Ace = require('ace/ace'); // This is an empty Object when I'm debugging with breakpoints
Config file:
// webpack.config.js
var webpack = require('webpack');
var path = require('path');
module.exports = {
entry: {
form: path.join(__dirname, 'static/main_files/form.js'),
vendor: [
'jquery',
'react',
'underscore',
'query-string',
'react-dnd',
'react-select-box'
]
},
output: {
path: path.join(__dirname, 'static/bundle'),
filename: '[name].bundle.js'
},
module: {
loaders: [{
test: /\.jsx$/,
loader: 'jsx-loader?insertPragma=React.DOM'
}],
noParse: [
/ace-builds.*/
]
},
resolve: {
extensions: ['', '.js', '.jsx'],
root: [
__dirname,
path.join(__dirname, 'static'),
path.join(__dirname, 'node_modules')
],
alias: {
jQueryMask: 'node_modules/jquery-mask-plugin/dist/jquery.mask',
twbsDropdown: 'node_modules/bootstrap-sass/assets/javascripts/bootstrap/dropdown',
'twbs-datetimepicker': 'node_modules/eonasdan-bootstrap-datetimepicker/src/js/bootstrap-datetimepicker',
ace: 'bower_components/ace-builds/src',
'select-box': 'node_modules/react-select-box/lib/select-box',
queryString: 'node_modules/query-string/query-string',
moment: 'node_modules/moment/moment'
}
},
plugins: [
new webpack.ResolverPlugin(
new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin("bower.json", ["main"])
),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})
]
};
It was not loaded on Chrome's Network panel
It is showing on Chrome's Sources panel (Don't know why because no ace.map file were loaded either)
Really running out of ideas of what I'm doing wrong here. Is there any good example that I can clone and test? (It can be another lib as well).
Use brace. It's a browserify compatible version of the ace editor which also works with webpack. Version 0.5.1 is using ace 1.1.9.
https://github.com/thlorenz/brace

Categories

Resources