总结别人对webpack的理解

转自:https://blog.csdn.net/liujie19901217/article/details/51026943

webpack就是一切都可以当成模块,require引入,不是js的通过loader解释一下,然后打包到一个js文件,html页面在script引入它,那么大的js只是减少了http请求次数

Webpack 是什么

webpack是一款模块加载器兼打包工具,它能把各种资源,例如JS(含JSX)、coffee、样式(含less/sass)、图片等都作为模块来使用和处理。 
简单说就是模块加载器,通过使用Webpack,能够像Node.js一样处理依赖关系,然后解析出模块之间的依赖,将代码打包。

为什么需要打包?

  • 像sass,JSX等代码虽然极大的提高了开发效率,但是本身并不被浏览器所识别,需要我们对其进行编译和打包,变成浏览器识别的代码
  • 模块化(让我们可以把复杂的代码细化为小的文件)
  • 优化加载速度(压缩和合并代码来提高加载速度,压缩可以减少文件体积,代码合并可以减少http请求)
  • 使用新的开发模式

webpack主要特性如下:

  • 同时支持CommonJS和AMD模块(对于新项目,推荐直接使用CommonJS);
  • 串联式模块加载器以及插件机制,让其具有更好的灵活性和扩展性,例如提供对CoffeeScript、ES6的支持;
  • 可以基于配置或者智能分析打包成多个文件,实现公共模块或者按需加载;
  • 支持对CSS,图片等资源进行打包,从而无需借助Grunt或Gulp(browserify只能打包JS文件);
  • 开发时在内存中完成打包,性能更快,完全可以支持开发过程的实时打包需求;
  • source map有很好的支持。

Source map(使调试更容易)

Source map就是一个信息文件,里面储存着位置信息。也就是说,转换后的代码的每一个位置,所对应的转换前的位置。有了它,出错的时候,除错工具将直接显示原始代码,而不是转换后的代码,这将给开发者带来了很大方便。 
详见传送门

安装 Webpack

首先得安装Node.js

  • 全局环境下安装,在任意目录,输入以下命令
//这是为了能够在全局环境中使用webpack命令
//非全局安装需使用node_modules/.bin/webpack
$ npm install webpack -g
  • 仅在项目在中安装,切换到项目根目录,输入以下命令
$ npm install webpack --save-dev
  • 检查是否安装成功,显示如下:
$ webpack -v

安装成功示例

更快捷的执行打包任务

{
  "name": "demo",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "start": "webpack-dev-server --progress --colors --hot --inline -d",
    "build": "webpack --progress --colors --minify"
  },
  "license": "ISC",
  "dependencies": {
  },
  "devDependencies": {
  }
}

执行类似于node_modules/.bin/webpack这样的命令不仅繁琐还容易出错,不过值得庆幸的是npm可以引导任务执行,对其进行配置后可以使用简单的npm start或者npm run build命令来代替这些繁琐的命令。在package.json中对npm的脚本部分进行相关设置即可,设置方法如上面的配置所示。 
**注意:**npm的start是一个特殊的脚本名称,它的特殊性在于:在命令行中使用npm start就可以执行相关命令,如果对应的此脚本名称不是start,想要在命令行中运行时,需要这样用npm run {script name}如上面例子中的npm run build。 
**特别说明:**package.json中的脚本部分已经默认在命令前添加了node_modules/.bin路径,所以无论是全局还是局部安装的Webpack,你都不需要写前面那指明详细的路径了。

配置

每个项目下都必须配置有一个 webpack.config.js ,它的作用如同常规的 gulpfile.js/Gruntfile.js ,就是一个配置项,告诉 webpack 它需要做什么。 
webpack.config.js配置详解 
这里给出我自己的配置:

var webpack = require('webpack');
var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js');
  module.exports = {
     noParse:[/jquery/],//表示跳过jquery,不对其进行编译,这样可以提高打包的速度
     plugins:[
     commonsPlugin,
     //配置了NoErrorsPlugin插件,用来跳过编译时出错的代码并记录,使编译后运行时的包不会发生错误
     new webpack.NoErrorsPlugin()
     ],
     entry: {
         index:'./src/js/startup.js'
     },
    //入口文件输出配置
     output:{
         //path: 打包好的资源存放的位置
         path:'./js',
         //filename: 打包后的文件名
         filename: '[name].bundle.js'
     },
     // externals: {     //排除构建文件外
  //        'react': 'React'
  //    },
     module: {
         //加载器配置
         //module.loaders 是最关键的一块配置。它告知 webpack 每一种文件都需要使用什么加载器来处理
        loaders:[
         {
           //用于匹配加载器支持的文件格式的正则表达式
            test: /\.css$/,
            //多个加载器通过"!"连接,加载器是从右向左开始使用的
            //loader指定了要使用的加载器类型
            loader: 'style-loader!css-loader'
        },
         {
         //配置信息的参数“?limit=8192”表示将所有小于8kb的图片都转为base64形式 (其实应该说超过8kb的才使用 url-loader 来映射到文件,否则转为data url形式)
              test: /\.(png|jpg)$/,
              //加载器支持通过查询字符串的方式接收参数
               loader: 'url-loader?limit=8192'
         },
         {
         //presets:指定哪些代码转换器将启用babel
             test: /\.js$/, 
             loader: 'babel-loader',
//exclude:/node_modules/,排除node_modules这个文件夹中的代码
//include:/(admin|consumer)//表示只针对这两个文件夹中的代码进行打包
//include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)
             exclude:/node_modules/,
             query:{
             presets:['es2015','react']
             }
         },
         {
             test: /\.jsx$/, 
             //?表示加载器支持通过查询字符串的方式接收参数
            //!表示多个加载器之间通过"!"连接
             loader: 'babel-loader!jsx-loader?harmony'
         }
         ]
     },
//文件解析配置
//会依次寻找不带后缀的文件,.js后缀文件以及.jsx后缀文件。先找到哪个是哪个
    resolve: { 
    extensions: ['', '.js', '.jsx'],//当requrie的模块找不到时,添加这些后缀
    root:'E:/myev/src',//绝对路径
    alias: {//别名配置

        }
     }
    }
 }

这里对Webpack的打包行为做了配置,主要分为几个部分:

  • plugins 是插件项(是一个数组):这里我们使用了一个 CommonsChunkPlugin 的插件,它用于提取多个入口文件的公共脚本部分,然后生成一个 common.js 来方便多页面之间进行复用。对于用到的插件,只需要将插件new出来放到数组中即可。
  • entry:指定打包的入口文件,每有一个键值对,就是一个入口文件
  • output:配置打包结果,path定义了输出的文件夹(即打包好的文件要放到哪里),filename则定义了打包结果文件的名称,filename里面的[name]会由entry中的键(这里是index)替换。publicPath:如果要使用webpack-dev-server(webpack配置服务器,端口号是8080)就需要配置(标明我们要从哪个地方获取打包好的文件)
  • externals:当我们想在项目中require一些其他的类库或者API,而又不想让这些类库的源码被构建到运行时文件中,这在实际开发中很有必要。此时我们就可以通过配置externals参数来解决这个问题。
  • resolve:定义了解析模块路径时的配置,常用的就是extensions,可以用来指定模块的后缀,这样在引入模块时就不需要写后缀了,会自动补全。比如 Hello.jsx 这样的文件就可以直接用 require(./Hello) 引用。 resolve 配置,配置查找模块的路径和扩展名和别名(方便书写)可以用 alias 指定从非npm引入的库,如

jquery:path.resolve(__dirname,'./bower_components/jquery/dist/jquery.js') , 
这样在 import 时可以替换引用路径。 
module:定义了对模块的处理逻辑,这里可以用loaders定义了一系列的加载器,以及一些正则。当需要加载的文件匹配test的正则时,就会调用后面的loader对文件进行处理,这正是webpack强大的原因。比如这里定义了凡是.js结尾的文件都是用babel-loader做处理,而.jsx结尾的文件会先经过babel-loader处理,然后经过jsx-loader处理。当然这些loader也需要通过npm install安装,“-loader”其实是可以省略不写的,多个loader之间用“!”连接起来。

Webpack还有很多其他的配置,具体可以参照它的配置文档 
对应各种不同文件类型的资源, Webpack 有对应的模块 loader。比如 CoffeeScript 用的是 coffee-loader, 其他还有很多。请参考相关文档 
在 Webpack 当中, 所有的资源都被当作是模块, js, css, 图片等等。因此, Webpack 当中 js 可以引用 css, css 中可以嵌入图片 dataUrl。

Webpack的加载器支持参数,jsx-loader就可以添加?harmony参数使其支持ES6语法。为了让Webpack识别什么样的资源应该用什么加载器去载入,需要在配置文件进行配置:通过正则表达式对文件名进行匹配。

加载器之间的级联是通过感叹号来连接,例如对于LESS资源,写法为style-loader!css-loader!less-loader从右向左开始使用,less->转为css字符串->使用style将代码放到页面style标签中。 
css-loader——将样式打包成字符串 
style-load——将样式字符串添加到页面的style标签中 
对于小型的图片资源,也可以将其进行统一打包,由url-loader实现,代码中url-loader?limit=8192含义就是对于所有小于8192字节的图片资源也进行打包。这在一定程度上可以替代Css Sprites方案,用于减少对于小图片资源的HTTP请求数量。

执行打包

如果通过npm install -g webpack方式安装webpack的话,可以通过命令行直接执行打包命令,比如: 
$ webpack –config webpack.config.js 
这样就会读取当前目录下的webpack.config.js作为配置文件执行打包操作

常用webpack命令: 
在开发环境构建一次 
webpack 
构建并生成源代码映射文件 
webpack -d 
在生成环境构建,压缩、混淆代码,并移除无用代码 
webpack -p 
快速增量构建,可以和其他选项一起使用 
webpack –watch 
progress 显示打包过程中的进度,colors打包信息带有颜色显示 
webpack –progress –colors

理解文件路径

require(‘lodash’) // 从模块目录查找 
require(‘./file’) // 按相对路径查找

CSS 及图片的引用

require(‘./bootstrap.css’); 
require(‘./myapp.less’);

var img = document.createElement(‘img’); 
img.src = require(‘./glyph.png’);

一个模块需要用它的文件路径来加载,看一下下面的这个结构:

–app 
——modules 
———–MyModule.js 
——main.js (entry point,入口文件) 
——utils.js

打开 main.js 然后可以通过下面两种方式引入 app/modules/MyModule.js

app/main.js

// ES6 
import MyModule from ‘./modules/MyModule.js’;

// CommonJS 
var MyModule = require(‘./modules/MyModule.js’);

最开始的 ./ 是 “相对当前文件路径” 
让我们打开 MyModule.js 然后引入 app/utils:

app/modules/MyModule.js

// ES6 相对路径 
import utils from ‘./../utils.js’;

// ES6 绝对路径 
import utils from ‘/utils.js’;

// CommonJS 相对路径 
var utils = require(‘./../utils.js’);

// CommonJS 绝对路径 
var utils = require(‘/utils.js’);

相对路径是相对当前目录。绝对路径是相对入口文件,这个案例中是 main.js。

CommonChunks插件

Common Chunks 插件的作用:提取代码中的公共模块,然后将公共模块打包到一个独立的文件中去,以便在其它的入口和模块中使用。 
我们在配置项中添加CommonChunksLoader的配置,使用它来提取公共模块。

var webpack = require('webpack');
var config = {
    entry:{
        main1:'./main1',
        main2:'./main2'
    },
    output:{
        filename:'bundle.[name].js'
    },
    plugins: [
        new  webpack.optimize.CommonsChunkPlugin('common.js', ['main1', 'main2'])
    ]
};
module.exports = config;

在配置文件中添加了webpack的引用(同时也要在项目目录下安装webpack),然后添加了plugins选项,引用了webpack.optimize.CommonsChunkPlugin来提取公共模块,参数common.js表示公共模块的文件名,后面的数组元素与entry一一对应,表示要提取这些模块中的公共模块。 
重新使用webpack打包后,看到生成的文件中多了一个common.js 
这里写图片描述 
这个common.js正是公共部分a和b两个模块。而生成的bundle.main1.js中只包含了c模块,bundle.main2.js中则没有包含任何其它模块。 
具体代码详见我的github:传送门 
最后要在HTML文件中引入公共部分common.js。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>CommonsChunkPlugin</title>
</head>
<body>
<script type="text/javascript" src="common.js"></script>
<script type="text/javascript" src="bundle.main1.js"></script>
</body>
</html>

运行结果: 
这里写图片描述

其他插件功能

OccurenceOrderPlugin:给经常使用的模块分配最小长度的id,这样可以减少文件大小。 
HotModuleReplacementPlugin:是热替换,热替换和dev-server的hot有什么区别?不用刷新页面,可用于生产环境。 
NoErrorsPlugin:在打包时不会因为错误而中断 
ProvidePlugin: 定义一些在import时能自动引入的变量,如定义了 $: 'jquery' 后,可以在文件中直接使用$,webpack可以自动帮你加上 var $ = require('jquery')。 
DllPlugin: 将一些模块预编译,类似windows里的dll,可以在项目中直接使用,无需再构建。注意要在output中指定 library ,并在DllPlugin中指定与其一致的 name ,在有多个入口时可以使用 [name] 和 [hash] 来区分,因为这个参数是要赋值到global上的,所以这里使用 [hash] 不容易出现变量名冲突的情况。 
DllReferencePlugin: 引用之前打包好的dll文件,注意下context参数,这个应该根据manifest.json文件中的引用情况来赋值,如果引用的都是npm安装的库,这里就填项目根目录就好了。 
DefinePlugin: 可以定义编译时的全局变量,有很多库(React, Vue等)会根据 NODE_ENV 这个变量来判断当前环境。为了尽可能减少包大小,在生产环境中要定义其为 JSON.stringify(“production”) 
optimize.UglifyJsPlugin: 配置压缩代码。 
optimize.DedupePlugin: 可以减少重复文件数。 
ExtractTextPlugin: 可以将所有css文件打包到一个css文件中。

Webpack-dev-server

Webpack有一个非常好用的功能叫做热替换(Hot-replace),尤其是结合React Hot Loader插件,开发过程中都不需要刷新浏览器,任何前端代码的更改都会实时的在浏览器中表现出来。 
需要安装Webpack-dev-server,一个轻量的node.js express服务器。

npm install webpack-dev-server --save-dev
  • 1

webpack-dev-server有两种模式支持自动刷新——iframe模式和inline模式。 
注意: 
iframe模式下:页面是嵌套在一个iframe下的**,在代码发生改变的时候,这个iframe会重新加载; 
使用iframe模式无需额外的配置,只需在浏览器输入 
http://localhost:8080/webpack-dev-server/index.html 
在inline模式下:一个小型的webpack-dev-server客户端会作为入口文件打包,这个客户端会在后端代码改变的时候刷新页面。 
使用inline模式有两种方式:命令行方式和Node.js API。 
命令行方式比较简单,只需加入–line选项即可。例如:

webpack-dev-server --inline
  • 1

使用–inline选项会自动把webpack-dev-server客户端加到webpack的入口文件配置中。 
其他相关参数介绍:

webpack-dev-server --progress --colors --hot --inline -p -d;
  • 1

–progress 显示打包进度 
–colors配置打包输出颜色显示 
–hot热加载,代码修改完后自动刷新 
–inline 是刷新后的代码自动注入到打包后的文件中(当源文件改变时会自动刷新页面
-d 是debug模式,输入一个source-map,并且可以看到每一个打包的文件 
-p 是对代码进行压缩 
参考博文: 
WebPack 简明学习教程 
WebPack 常用功能介绍 
Webpack 指南 
关于简聊 Webpack 配置的一些注释 
Webpack-dev-server结合后端服务器的热替换配置 
WEBPACK DEV SERVER 
webpack和webpack-dev-server配置的个人小结 
webpack使用优化 
入门 Webpack,看这篇就够了


阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页