It is mainly used for learning Webpack, the original address is github.com/ruanyf/webp…
Installation Guide
First, install Webpack and webpack-dev-server globally
$ npm i -g webpack webpack-dev-server
Copy the code
Then clone ruan Yifeng’s warehouse
$ git clone https://github.com/ruanyf/webpack-demos.git
Copy the code
Install dependencies
$ cd webpack-demos
$ npm install
Copy the code
Now go into the demo* directory and run them
$ cd demo01
$ npm run dev
Copy the code
The above code does not automatically open your browser, you need to manually visit http://127.0.0.1:8080
Preface: What is Webpack
Webpack is a front-end tool for building Javascript module scripts for use by browsers. It’s similar to Browserify, but can do a lot more
$ browserify main.js > bundle.js
# the above and below codes have the same effect
$ webpack main.js bundle.js
Copy the code
Webpack requires a configuration file called webpack.config.js, which is a CommonJS module.
Module.exports = {entry: // webpack.config.js contents module.exports = {entry:'./main.js',
output: {
filename: 'bundle.js'}};Copy the code
When webpack.config.js is built, webpack can be run without arguments
$ webpack
Copy the code
There are some must-know parameter options below
webpack
— Build commands at development timewebpack -p
Build commands when releasing the productwebpack --watch
— Builds for incremental developmentwebpack -d
— Including Source Mapswebpack --colors
Make the build output look better
You can customize the scripts option in webpack.config.js, as shown below
// package.json
{
// ...
"scripts": {
"dev": "webpack-dev-server --devtool eval --progress --colors"."deploy": "NODE_ENV=production webpack -p"} / /... }Copy the code
Demo01: entry file
The import file is used by Webpack to read it and build bundle.js for example, main.js is an import file
// main.js
document.write('<h1>Hello World</h1>');
Copy the code
index.html
<html>
<body>
<script type="text/javascript" src="bundle.js"></script>
</body>
</html>
Copy the code
Webpack builds bundle.js from webpack.config.js
// webpack.config.js
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'}};Copy the code
Run the following command and go to http://127.0.0.1:8080
$ cd demo01
$ npm run dev
Copy the code
Demo02: Multiple entry files
Webpack allows multiple entry files to exist, which is useful in multi-page apps where each page has a different entry file.
// main1.js
document.write('<h1>Hello World</h1>');
// main2.js
document.write('<h2>Hello Webpack</h2>');
Copy the code
index.html
<html>
<body>
<script src="bundle1.js"></script>
<script src="bundle2.js"></script>
</body>
</html>
Copy the code
webpack.config.js
module.exports = {
entry: {
bundle1: './main1.js',
bundle2: './main2.js'
},
output: {
filename: '[name].js'}};Copy the code
Demo03:Babel-loader
Loaders are preprocessors that convert resource files in your app before the Webpack build process. For example, Babel-Loader can turn JSX/ES6 files into regular JS files, after which Webpack can start building them. Webpack official documentation has a list of loaders at the address main. JSX is a JSX file
// main.jsx
const React = require('react');
const ReactDOM = require('react-dom'); ReactDOM.render( <h1>Hello, world! </h1>, document.querySelector('#wrapper'));Copy the code
index.html
<html>
<body>
<div id="wrapper"></div>
<script src="bundle.js"></script>
</body>
</html>
Copy the code
webpack.config.js
module.exports = {
entry: './main.jsx',
output: {
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.jsx? $/, exclude: /node_modules/, use: { loader:'babel-loader',
options: {
presets: ['es2015'.'react'}}}]}};Copy the code
In the above code, two plug-ins of babel-Loader, babel-preset- ES2015 and babel-preset-react, are needed to switch ES6 and react.
Demo04:CSS-loader
Webpack allows CSS to be included in JS files that require CSS-loader to process main.js
require('./app.css');
Copy the code
app.css
body {
background-color: blue;
}
Copy the code
index.html
<html>
<head>
<script type="text/javascript" src="bundle.js"></script>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
Copy the code
webpack.config.js
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
},
module: {
rules:[
{
test: /\.css$/,
use: [ 'style-loader'.'css-loader']},]}};Copy the code
Attention! You must use two loaders to transform CSS files. Css-loader is used to read CSS files for conversion, and another style-loader inserts < Style > tags into the HTML. And then open up the server
$ cd demo04
$ npm run dev
Copy the code
In fact, Webpack inserts the contents of the CSS file directly into index.html
<head>
<script type="text/javascript" src="bundle.js"></script>
<style type="text/css">
body {
background-color: blue;
}
</style>
</head>
Copy the code
Demo5: Image loader
Webpack can include images in the JS file main.js
var img1 = document.createElement("img");
img1.src = require("./small.png");
document.body.appendChild(img1);
var img2 = document.createElement("img");
img2.src = require("./big.png");
document.body.appendChild(img2);
Copy the code
index.html
<html>
<body>
<script type="text/javascript" src="bundle.js"></script>
</body>
</html>
Copy the code
webpack.config.js
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
},
module: {
rules:[
{
test: /\.(png|jpg)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192}}]}};Copy the code
Url-loader converts the image file to a tag. If the image size is 8192 bytes, it converts the image to a Data URL. Otherwise, it converts the image to a normal file URL.
<img src="data:image/png; base64,iVBOR... uQmCC">
<img src="4853ca667a2b8b8844eb2693ac1b2578.png">
Copy the code
Demo06:CSS Module
css-loader? Modules can use CSS Modules, which give you a local scope for the CSS in your JS file Module, or global(selector) to make CSS global. index.html
<html>
<body>
<h1 class="h1">Hello World</h1>
<h2 class="h2">Hello Webpack</h2>
<div id="example"></div>
<script src="./bundle.js"></script>
</body>
</html>
Copy the code
app.css
/ *local scope */
.h1 {
color:red;
}
/* global scope */
:global(.h2) {
color: blue;
}
Copy the code
main.jsx
var React = require('react');
var ReactDOM = require('react-dom');
var style = require('./app.css');
ReactDOM.render(
<div>
<h1 className={style.h1}>Hello World</h1>
<h2 className="h2">Hello Webpack</h2>
</div>,
document.getElementById('example'));Copy the code
webpack.config.js
module.exports = {
entry: './main.jsx',
output: {
filename: 'bundle.js'
},
module: {
rules:[
{
test: /\.js[x]? $/, exclude: /node_modules/, use: { loader:'babel-loader',
options: {
presets: ['es2015'.'react'}}}, {test: /\.css$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
modules: true}}]}};Copy the code
Visit http://127.0.0.1:8080 and you’ll see that only H1 is red because its CSS is local scoped, and h2 is blue because it’s global scoped.
Demo07:UglifyJs Plugin
Webpack uses a plug-in system to extend its functionality. For example, the UglifyJs Plugin is used to compress JS code and make JS files smaller. main.js
var longVariableName = 'Hello';
longVariableName += ' World';
document.write('<h1>' + longVariableName + '</h1>');
Copy the code
index.html
<html>
<body>
<script src="bundle.js"></script>
</body>
</html>
Copy the code
webpack.config.js
var webpack = require('webpack');
var UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
},
plugins: [
new UglifyJsPlugin()
]
};
Copy the code
After accessing the server, you can see main.js minimized to the following code:
var o="Hello"; o+=" World",document.write("<h1>"+o+"</h1>")
Copy the code
(Translation: in the last few code of bundle.js, here’s the code)
Demo08:HTML Webpack Plugin and Open Browser Webpack Plugin
Html-webpack-plugin can create index.html for you. Open-browser-webpack-plugin can open a new browser TAB (TAB) main.js when webpack loads
document.write('<h1>Hello World</h1>');
Copy the code
webpack.config.js
var HtmlwebpackPlugin = require('html-webpack-plugin');
var OpenBrowserPlugin = require('open-browser-webpack-plugin');
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
},
plugins: [
new HtmlwebpackPlugin({
title: 'Webpack-demos',
filename: 'index.html'
}),
new OpenBrowserPlugin({
url: 'http://localhost:8080'}})];Copy the code
Now you don’t have to manually create index.html or open a browser.
Demo09: Environment Flags
Using environment variables makes some code available only in the development environment. main.js
document.write('<h1>Hello World</h1>');
if (__DEV__) {
document.write(new Date());
}
Copy the code
index.html
<html>
<body>
<script src="bundle.js"></script>
</body>
</html>
Copy the code
webpack.config.js
var webpack = require('webpack');
var devFlagPlugin = new webpack.DefinePlugin({
__DEV__: JSON.stringify(JSON.parse(process.env.DEBUG || 'false'))}); module.exports = { entry:'./main.js',
output: {
filename: 'bundle.js'
},
plugins: [devFlagPlugin]
};
Copy the code
Now pass the environment variables to Webpack. Open demo09/package.json and find the following scripts option
// package.json
{
// ...
"scripts": {
"dev": "cross-env DEBUG=true webpack-dev-server --open",}, / /... }Copy the code
Demo10: Code separation
In large Web applications, putting all your code in one file is inefficient. Webpack allows you to split large JS files into chunks. In particular, if some code blocks are needed only in certain circumstances, they will be loaded on demand. Webpack uses require.ensure to define a split point
// main.js
require.ensure(['./a'].function (require) {
var content = require('./a');
document.open();
document.write('<h1>' + content + '</h1>');
document.close();
});
Copy the code
Require. Ensure tells Webpack./ A that js needs to be separated from bundle.js as a separate block file
// a.js
module.exports = 'Hello World';
Copy the code
Now Webpack cares about dependencies, output files, runtime stuff. You don’t have to put extra stuff in index.html and webpack.config.js
<html>
<body>
<script src="bundle.js"></script>
</body>
</html>
Copy the code
webpack.config.js
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'}};Copy the code
After visiting the server, you will not feel any difference. In fact, Webpack will build main.js and A.js into different blocks (bundle.js and 0.bundle.js) and then load 0.bundle.js on demand from bundle.js
Demo11: Code separation under bundle-loader
Another way to split code is bundle-loader
// main.js
// Now a.js is requested, it will be bundled into another file
var load = require('bundle-loader! ./a.js');
// To wait until a.js is available (and get the exports)
// you need to async wait for it.
load(function(file) {
document.open();
document.write('<h1>' + file + '</h1>');
document.close();
});
Copy the code
require(‘bundle-loader! ./a.js’) tells Webpack to load A.js from other blocks. Now main.js is built as bundle.js, and a.js is built as 0.bundle.js
Demo12: general block
There are common blocks in multiple JS scripts. With the CommonsChunkPlugin you can extract common parts from different files, which is very useful for browser caching to save bandwidth.
// main1.jsx
var React = require('react');
var ReactDOM = require('react-dom');
ReactDOM.render(
<h1>Hello World</h1>,
document.getElementById('a')); // main2.jsx var React = require('react');
var ReactDOM = require('react-dom');
ReactDOM.render(
<h2>Hello Webpack</h2>,
document.getElementById('b'));Copy the code
index.html
<html>
<body>
<div id="a"></div>
<div id="b"></div>
<script src="commons.js"></script>
<script src="bundle1.js"></script>
<script src="bundle2.js"></script>
</body>
</html>
Copy the code
Commons.js above is a common part of main1.jsx and main2.jsx. As you might expect, commons.js includes react and react-dom webpack.config.js
var webpack = require('webpack');
module.exports = {
entry: {
bundle1: './main1.jsx',
bundle2: './main2.jsx'
},
output: {
filename: '[name].js'
},
module: {
rules:[
{
test: /\.js[x]? $/, exclude: /node_modules/, use: { loader:'babel-loader',
options: {
presets: ['es2015'.'react']
}
}
},
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: "commons",
// (the commons chunk name)
filename: "commons.js",
// (the filename of the commons chunk)
})
]
}
Copy the code
Demo13:Vendor chunk
With CommonsChunkPlugin, you can extract the official library from JS scripts into a separate file called main.js
var $ = require('jquery');
$('h1').text('Hello World');
Copy the code
index.html
<html>
<body>
<h1></h1>
<script src="vendor.js"></script>
<script src="bundle.js"></script>
</body>
</html>
Copy the code
webpack.config.js
var webpack = require('webpack');
module.exports = {
entry: {
app: './main.js',
vendor: ['jquery'],
},
output: {
filename: 'bundle.js'
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: 'vendor.js'}})];Copy the code
In the code above, Entry.vendor :[‘jquery’] tells Webpack that jquery should be included in the generic block vendor.js. If you want a module to be used as a global variable in different modules, such as $or jquery instead of requiring (‘jquery’) in every file, use the ProvidePlugin. It automatically loads modules without needing to import or require them everywhere
// main.js
$('h1').text('Hello World');
// webpack.config.js
var webpack = require('webpack');
module.exports = {
entry: {
app: './main.js'
},
output: {
filename: 'bundle.js'
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'}})];Copy the code
Of course, in Demo13, you need to load jquery.js globally yourself
Demo14: Exposes global variables
If you want to use global variables, you don’t need to include them in the Webpack, you can use the externals field in webpack.config.js. For example, we have a data.js
// data.js
var data = 'Hello World';
Copy the code
index.html
<html>
<body>
<script src="data.js"></script>
<script src="bundle.js"></script>
</body>
</html>
Copy the code
Note that Webpack only builds bundle.js, not data.js. We can use data as a global variable
// webpack.config.js
module.exports = {
entry: './main.jsx',
output: {
filename: 'bundle.js'
},
module: {
rules:[
{
test: /\.js[x]? $/, exclude: /node_modules/, use: { loader:'babel-loader',
options: {
presets: ['es2015'.'react']
}
}
},
]
},
externals: {
// require('data') is external and available
// on the global var data
'data': 'data'}};Copy the code
At this point, you can require(‘data’) as a module variable, which is actually a global variable
// main.jsx
var data = require('data');
var React = require('react');
var ReactDOM = require('react-dom');
ReactDOM.render(
<h1>{data}</h1>,
document.body
);
Copy the code
You can also add react and react-dom to externals, which significantly reduces the bundle.js build time and file size
Demo15:React router
This Demo uses Webpack to build an official React Router. Imagine a small application with a dashboard, inbox, and calendar
+---------------------------------------------------------+ | +---------+ +-------+ +--------+ | | |Dashboard| | Inbox | |Calendar| Loggedinas Jane | | +---------+ +-------+ +--------+ | +---------------------------------------------------------+ | | | Dashboard | | | | | | +---------------------+ +----------------------+ | | | | | | | | | + + | +---------> | | | | | | | | | | | | | + | | +-------------> | | | | | | + | | | | | | | | | | | | | | | | +-+---+----+-----+----+ +----------------------+ | | | +---------------------------------------------------------+Copy the code
webpack.config.js
module.exports = {
entry: './index.js',
output: {
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.css$/,
use: [ 'style-loader'.'css-loader'] {},test: /\.jsx? $/, exclude: /node_modules/, use: { loader:'babel-loader',
options: {
presets: ['es2015'.'react']}}},]}};Copy the code
index.js
import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter, Switch, Route, Link } from 'react-router-dom';
import './app.css';
class App extends React.Component {
render() {
return (
<div>
<header>
<ul>
<li><Link to="/app">Dashboard</Link></li>
<li><Link to="/inbox">Inbox</Link></li>
<li><Link to="/calendar">Calendar</Link></li>
</ul>
Logged in as Jane
</header>
<main>
<Switch>
<Route exact path="/" component={Dashboard}/>
<Route path="/app" component={Dashboard}/>
<Route path="/inbox" component={Inbox}/>
<Route path="/calendar" component={Calendar}/>
<Route path="*"component={Dashboard}/> </Switch> </main> </div> ); }}; class Dashboard extends React.Component {render() {
return( <div> <p>Dashboard</p> </div> ); }}; class Inbox extends React.Component {render() {
return( <div> <p>Inbox</p> </div> ); }}; class Calendar extends React.Component {render() {
return( <div> <p>Calendar</p> </div> ); }}; render(( <BrowserRouter> <Route path="/" component={App} />
</BrowserRouter>
), document.querySelector('#app'));
Copy the code
index.html
<html>
<body>
<div id="app"></div>
<script src="/bundle.js"></script>
</body>
</htmL>
Copy the code
Then go to http://127.0.0.1:8080