博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[翻译]阮一峰webpack教程(Demo集合)
阅读量:6860 次
发布时间:2019-06-26

本文共 13406 字,大约阅读时间需要 44 分钟。

翻译它主要是用于学习Webpack,原地址为

安装使用指南

首先,全局安装Webpack和webpack-dev-server

$ npm i -g webpack webpack-dev-server复制代码

然后克隆clone阮一峰的仓库

$ git clone https://github.com/ruanyf/webpack-demos.git复制代码

安装依赖

$ cd webpack-demos$ npm install复制代码

现在开始进入demo*目录并且运行它们

$ cd demo01$ npm run dev复制代码

上面的代码不会自动的打开你的浏览器,需要手动访问

前言:Webpack是什么

Webpack用于构建Javascript模块脚本来给浏览器使用的前端工具。

它和Browserify很像,但是能做更多的事~

$ browserify main.js > bundle.js# 上下代码作用相同$ webpack main.js bundle.js复制代码

Webpack需要一个名为webpack.config.js的配置文件,这个文件就是一个CommonJS的模块(module)

// webpack.config.js的内容module.exports = {  entry: './main.js',  output: {    filename: 'bundle.js'  }};复制代码

当建好webpack.config.js后就能直接运行Webpack,而不加参数

$ webpack复制代码

有一些必须知道的参数选项如下

  • webpack——开发时的构建命令
  • webpack -p——发布产品时的构建命令
  • webpack --watch——用于增量开发的构建
  • webpack -d——包括source maps
  • webpack --colors——让构建输出更好看

可以在定制webpack.config.js中的scripts选项,如下所示

// package.json{  // ...  "scripts": {    "dev": "webpack-dev-server --devtool eval --progress --colors",    "deploy": "NODE_ENV=production webpack -p"  },  // ...}复制代码

Demo01:入口文件

入口文件用来Webpack读取它然后构建bundle.js

例如下面,main.js就是一个入口文件

// main.jsdocument.write('

Hello World

');复制代码

index.html

        复制代码

Webpack依据webpack.config.js来构建bundle.js

// webpack.config.jsmodule.exports = {  entry: './main.js',  output: {    filename: 'bundle.js'  }};复制代码

运行下面的命令然后访问

$ cd demo01$ npm run dev复制代码

Demo02:多个入口文件

Webpack允许多个入口文件存在,在多页面的app中很有用,每个页面有不同的入口文件。

// main1.jsdocument.write('

Hello World

');// main2.jsdocument.write('

Hello Webpack

');复制代码

index.html

            复制代码

webpack.config.js

module.exports = {  entry: {    bundle1: './main1.js',    bundle2: './main2.js'  },  output: {    filename: '[name].js'  }};复制代码

Demo03:Babel-loader

加载器(Loaders)是一些预处理器,用于在Webpack的构建过程前,将你app里的一些资源文件进行转换。

例如,Babel-loader能够将JSX/ES6文件转为普通的JS文件,之后Webpack能够开始构建它们。Webpack官方文档有一个加载器的列表
main.jsx是一个JSX文件

// main.jsxconst React = require('react');const ReactDOM = require('react-dom');ReactDOM.render(  

Hello, world!

, document.querySelector('#wrapper'));复制代码

index.html

      
复制代码

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']          }        }      }    ]  }};复制代码

在上面的代码里需要babel-loader的两个插件babel-preset-es2015和babel-preset-react来转换ES6和React(翻译:现在为废弃了,)

Demo04:CSS-loader

Webpack允许在JS文件中包含CSS,需要CSS-loader对这些CSS进行处理

main.js

require('./app.css');复制代码

app.css

body {  background-color: blue;}复制代码

index.html

              

Hello World

复制代码

webpack.config.js

module.exports = {  entry: './main.js',  output: {    filename: 'bundle.js'  },  module: {    rules:[      {        test: /\.css$/,        use: [ 'style-loader', 'css-loader' ]      },    ]  }};复制代码

注意!必须使用两个加载器来转换CSS文件。CSS-loader用来读取CSS文件来转换,另一个Style-loader用来往HTML中插入<style>标签。

然后打开server

$ cd demo04$ npm run dev复制代码

事实上,Webpack将CSS文件的内容直接插入到index.html

    复制代码

Demo5: Image loader

Webpack能够将图片包含进JS文件中

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);复制代码

index.html

        复制代码

webpack.config.js

module.exports = {  entry: './main.js',  output: {    filename: 'bundle.js'  },  module: {    rules:[      {        test: /\.(png|jpg)$/,        use: [          {            loader: 'url-loader',            options: {              limit: 8192            }          }        ]      }    ]  }};复制代码

url-loader将image文件转为<img>标签,如果图片大小小鱼8192字节,它将转换为Data url(翻译:图片变为Base64编码,减少请求次数),否则,他将转为普通文件URL。

复制代码

Demo06:CSS Module

css-loader?modules(请求参数为modules)能够使用CSS Module,CSS Module带给你的JS文件模块中的CSS一个局部作用域,也可以使用:global(selector)让CSS变为全局作用。

index.html

  

Hello World

Hello Webpack

复制代码

app.css

/* local scope */.h1 {  color:red;}/* global scope */:global(.h2) {  color: blue;}复制代码

main.jsx

var React = require('react');var ReactDOM = require('react-dom');var style = require('./app.css');ReactDOM.render(  

Hello World

Hello Webpack

, document.getElementById('example'));复制代码

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             }          }        ]      }    ]  }};复制代码

访问会看到只有h1是红色的,因为他的CSS是局部作用域,然后所以h2都是蓝色的,因为它是全局作用域。

Demo07:UglifyJs Plugin

Webpack用插件系统来扩展他的功能。例如,,它用来压缩JS代码,使得JS文件体积变小。

main.js

var longVariableName = 'Hello';longVariableName += ' World';document.write('

' + longVariableName + '

');复制代码

index.html

  复制代码

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()  ]};复制代码

在访问服务器后,可以看到main.js最小化为如下代码:

var o="Hello";o+=" World",document.write("

"+o+"

")复制代码

(翻译:是在bundle.js的最后几个代码那,是这些代码)

Demo08:HTML Webpack Plugin和Open Browser Webpack Plugin

这个demo用来展示如何加载第三方插件

html-webpack-plugin能为你创建index.htmlopen-browser-webpack-plugin能够在Webpack加载时打开一个新的浏览器标签(tab)
main.js

document.write('

Hello World

');复制代码

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'    })  ]};复制代码

现在你不用手动创建index.html也不用手动打开浏览器了。

Demo09:环境变量(Environment flags)

使用环境变量让一些代码只能在开发环境时使用。

main.js

document.write('

Hello World

');if (__DEV__) { document.write(new Date());}复制代码

index.html

  复制代码

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]};复制代码

现在传递环境变量给Webpack。打开demo09/package.json,找到如下scripts选项

// package.json{  // ...  "scripts": {    "dev": "cross-env DEBUG=true webpack-dev-server --open",  },  // ...}复制代码

Demo10:代码分离

在大型web应用中,将所有代码放入一个文件是十分低效的。Webpack允许你将大型JS文件分成多块。特别的,如果一些代码块只是在某些情况下需要,那么这些代码块会按需加载。

Webpack使用require.ensure来定义一个分割点

// main.jsrequire.ensure(['./a'], function (require) {  var content = require('./a');               document.open();  document.write('

' + content + '

'); document.close();});复制代码

require.ensure告诉Webpack ./a,js需要从bundle.js中分离出来作为一个单独的块文件

// a.jsmodule.exports = 'Hello World';复制代码

现在Webpack关心依赖、输出文件、运行时的东西。你不必将多余的东西放到index.htmlwebpack.config.js

index.html

        复制代码

webpack.config.js

module.exports = {  entry: './main.js',  output: {    filename: 'bundle.js'  }};复制代码

访问服务器后,你感觉不到任何不同。实际上,Webpack将构建main.jsa.js到不同的块中(bundle.js0.bundle.js),然后从bundle.js中按需加载0.bundle.js

Demo11:bundle-loader下的代码分离

另一个代码分割的方式是bundle-loader

// main.js// Now a.js is requested, it will be bundled into another filevar 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('

' + file + '

'); document.close();});复制代码

require('bundle-loader!./a.js')告诉Webpack从其他块加载a.js

现在main.js构建为bundle.jsa.js构建为0.bundle.js

Demo12:通用块

在多个JS脚本中有通用块,通过CommonsChunkPlugin你能提取不同文件中的通用部分,对于浏览器缓存来节省带宽是非常有用的。

// main1.jsxvar React = require('react');var ReactDOM = require('react-dom');ReactDOM.render(  

Hello World

, document.getElementById('a'));// main2.jsxvar React = require('react');var ReactDOM = require('react-dom');ReactDOM.render(

Hello Webpack

, document.getElementById('b'));复制代码

index.html

      
复制代码

上面的commons.jsmain1.jsxmain2.jsx的通用部分。正如你想的,commons.js包括reactreact-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)    })  ]}复制代码

Demo13:Vendor chunk

通过CommonsChunkPlugin,你能从JS脚本提取官方库到单独的文件中

main.js

var $ = require('jquery');$('h1').text('Hello World');复制代码

index.html

      

复制代码

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'    })  ]};复制代码

在上面的代码中,entry.vendor:['jquery']告诉Webpack,jquery应该被包括到通用块vendor.js中。

如果你想要一个模块作为全局变量来在不同的模块中使用,比如不用在每个文件中require('jquery'),而是让$或者jQuery作为全局变量,需要使用ProvidePlugin,它能够自动加载模块而不需要到处import或者是require

// main.js$('h1').text('Hello World');// webpack.config.jsvar webpack = require('webpack');module.exports = {  entry: {    app: './main.js'  },  output: {    filename: 'bundle.js'  },  plugins: [    new webpack.ProvidePlugin({      $: 'jquery',      jQuery: 'jquery'    })  ]};复制代码

当然,在Demo13中,你需要自己全局加载jquery.js

Demo14:公开全局变量

如果你想用一些全局变量,不需要在Webpack包中包含他们,你可以使用webpack.config.js里的externals字段

例如,我们有一个data.js

// data.jsvar data = 'Hello World';复制代码

index.html

            复制代码

注意,Webpack只会构建bundle.js, 而不会构建data.js

我们可以把data作为全局变量

// webpack.config.jsmodule.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'  }};复制代码

此时,你可以require('data')作为模块变量,实际上它是一个全局变量

// main.jsxvar data = require('data');var React = require('react');var ReactDOM = require('react-dom');ReactDOM.render(  

{data}

, document.body);复制代码

同样可以将reactreact-dom放入externals,这样显著的降低构建bundle.js的时间和文件大小

Demo15:React router

这个Demo使用Webpack来构建React router的官方样例

先想象一个有控制板、收件箱、日历的小应用

+---------------------------------------------------------+| +---------+ +-------+ +--------+                        || |Dashboard| | Inbox | |Calendar|      Logged in as Jane || +---------+ +-------+ +--------+                        |+---------------------------------------------------------+|                                                         ||                        Dashboard                        ||                                                         ||                                                         ||   +---------------------+    +----------------------+   ||   |                     |    |                      |   ||   | +              +    |    +--------->            |   ||   | |              |    |    |                      |   ||   | |   +          |    |    +------------->        |   ||   | |   |    +     |    |    |                      |   ||   | |   |    |     |    |    |                      |   ||   +-+---+----+-----+----+    +----------------------+   ||                                                         |+---------------------------------------------------------+复制代码

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']          }        }      },    ]  }};复制代码

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 (      
  • Dashboard
  • Inbox
  • Calendar
Logged in as Jane
); }};class Dashboard extends React.Component { render() { return (

Dashboard

); }};class Inbox extends React.Component { render() { return (

Inbox

); }};class Calendar extends React.Component { render() { return (

Calendar

); }};render((
), document.querySelector('#app'));复制代码

index.html

      
复制代码

然后访问

转载地址:http://qiayl.baihongyu.com/

你可能感兴趣的文章
免费IDE编辑器才是Java程序员的最爱
查看>>
一张图读懂2016年CIO最关心的IT趋势
查看>>
混合云?行业云?“合脚”的才是好用的云
查看>>
掘金全球最大商务差旅市场 SAP旗下Concur联合中数通进军中国
查看>>
大变样:Firefox新一代UI “Photon”设计曝光
查看>>
云计算、IoT和SDN为企业网带来最大的问题
查看>>
云趋势下的Windows平台:生存并快乐着
查看>>
不要再在JavaScript中写 CSS了
查看>>
Gartner:云安全进入高速发展期
查看>>
云存储能否成为数据安全灵药?几个角度全方位剖析
查看>>
未来几年SDN将进一步提升云服务利润率
查看>>
手把手教你用 Python 和 Scikit-Learn 实现垃圾邮件过滤
查看>>
Hinton亲自讲解迄今未发表工作:胶囊理论的核心概念到底是什么?
查看>>
光伏业需要一次国内“双反”
查看>>
小微企业都在用的一体化管理解决方案
查看>>
Sql Server 2008 为开发带来的新特性
查看>>
Realm为Node.js发布对象数据库
查看>>
物联网行业将掀起新一轮并购潮 步入整合期
查看>>
夏日炎炎 构筑安防线 这些知识你Get到了吗?
查看>>
《C语言程序设计:问题与求解方法》——2.4节C语言源程序的次要组成成分:编译预处理命令、注释和声明...
查看>>