Webpack2入门

webpack 2 将在其文档完成之后正式发布。但这并不意味着不可以开始使用它,如果你知道怎么配置的话。

什么是 Webpack?

简单来说,Webpack 就是一个针对 JavaScript 代码的模块打包工具。但是自发布以来,它演变成了一个针对所有前端代码的管理工具(不管是其本身有意还是社区的意愿)。

旧的任务运行工具处理方式:HTML、CSS 和 JavaScript 都是分离的。必须分别对每一项进行管理,并且还要确保所有东西正确地部署到生产环境。

像 Gulp 这样的任务运行工具可以操作很多不同的预处理器和编译器,但是在所有情况下,它都需要接收一个源码输入并将其处理成一个编译好的输出。然而,它是在不关心整个系统的情况下逐个去处理的。这就是开发者的负担了:检查任务运行工具有无遗漏的地方,并为所有改动的部分找到正确的方式,将它们在生产环境上协调一致。

Webpack 通过一个大胆的询问试图减轻开发者的负担:如果开发过程的某个部分可以自己管理依赖会怎么样?如果我们可以以这样一种方式来简单地写代码:构建过程仅基于最后所需要的东西来管理它自己,会怎么样?

Webpack 处理方式:如果是 Webpack 知道的代码,那么它就只会打包实际在生产环境当中使用的部分。

如果你是过去几年里 Web 社区当中的一员,那么你肯定已经知道首选解决问题的方法:使用 JavaScript 构建。所以 Webpack 试图通过用 JavaScript 传递依赖来使构建过程变得更加容易。但是它设计的精妙之处并不在于简单的代码管理部分,而在于它的管理层面是百分百有效的 JavaScript(还有 Node 特性)。Webpack 使你有机会写出一些对整体系统有更好感知的 JavaScript 代码。

换句话说:你不是为了 Webpack 写代码,而是为了你的项目写代码。而且 Webpack 在保持进步(当然包括某些配置)。

总而言之,如果你曾经挣扎于下面这些情况中的其中之一:

  • 不小心将一些不需要的样式表或者 JS 库引入生产环境,导致项目体积变大
  • 遇到作用域问题 - 不管是来自 CSS 还是 JavaScript
  • 不停寻找一个好的系统好让你可以在 JavaScript 代码里使用 Node 或 Bower 的模块,或者依赖一系列疯狂的后端配置来正确地使用那些模块
  • 需要优化资源分发机制却又担心会破坏掉某些东西

…那么你就可以受益于 Webpack 了。它通过让 JavaScript 取代开发者的大脑来关心依赖和加载顺序,轻松地解决了上面这些问题。最好的部分是什么?Webpack 甚至可以在服务端无缝运行,这意味着你仍然可以使用 Webpack 来构建渐进式增强的网站。

第一步

在这篇教程里我们将使用 Yarnbrew install yarn)来替代 npm,但这完全取决于你自己,它们做的是同样的事情。打开到项目文件夹,在命令行窗口运行下面的命令添加 Webpack 2 到全局包和本地项目里:


1

2


yarn global add [email protected]2.1.0-beta.25 [email protected]2.1.0-beta.10

yarn add --dev [email protected]2.1.0-beta.25 [email protected]2.1.0-beta.10

然后在根目录新建一个 webpack.config.js 文件用来声明 Webpack 的配置:


1

2

3

4

5

6

7

8

9

10

11

12

13

14


‘use strict‘;

const webpack = require("webpack");

module.exports = {

context: __dirname + "/src",

entry: {

app: "./app.js",

},

output: {

path: __dirname + "/dist",

filename: "[name].bundle.js",

},

};

注意:__dirname指的是根目录。

还记得 Webpack “知道”项目里发生了什么吗?它是通过读取你的代码知道的(不用担心,它签署了一份保密协议)。Webpack 基本做了下面这些事情:

  1. 从 context 对应的文件夹开始…
  2. …寻找 entry 里所有的文件名…
  3. …然后读取它们的内容。在解析代码时,每一个通过 import(ES6) 或 require()(Node) 引入的依赖都会被打包到最终的构建结果当中。它会接着搜索那些依赖,以及那些依赖的依赖,直到“依赖树”的叶子节点 — 只打包它所需要的依赖,没有其他的东西。
  4. 接着,Webpack 将所有东西打包到 output.path 对应的文件夹里,使用 output.filename 对应的命名模板来命名([name] 被 entry 里的对象键值所替代)

所以如果 src/app.js 文件看起来像下面这样的话(假设提前运行了 yarn add --dev moment):


1

2

3

4

5


‘use strict‘;

import moment from ‘moment‘;

var rightNow = moment().format(‘MMMM Do YYYY, h:mm:ss a‘);

console.log( rightNow );

// "October 23rd 2016, 9:30:24 pm"

接着运行:


1

webpack -p

注意:p 标记表示“生产(production)”模式并且会压缩或丑化(uglify/minify)输出。

然后它将输出一个 dist/app.bundle.js 文件,作用就是打印出当前日期和时间到控制台。注意到 Webpack 自动知道了 ‘moment‘ 指的是什么(但如果已经有一个 moment.js 在你的目录当中,那么 Webpack 默认就会优先使用这个而不是 moment 的 Node 模块)。

处理多个文件

你只需要通过修改 entry 对象就可以指定任意数量所期望的 entry 或 output 点。

多个文件,打包在一起


1

2

3

4

5

6

7

8

9

10

11

12

13

14


‘use strict‘;

const webpack = require("webpack");

module.exports = {

context: __dirname + "/src",

entry: {

app: ["./home.js", "./events.js", "./vendor.js"],

},

output: {

path: __dirname + "/dist",

filename: "[name].bundle.js",

},

};

所有文件会按数组顺序一起打包到 dist/app.bundle.js 一个文件当中。

多个文件,多个输出


1

2

3

4

5

6

7

8

9

10

11

12

13

14


const webpack = require("webpack");

module.exports = {

context: __dirname + "/src",

entry: {

home: "./home.js",

events: "./events.js",

contact: "./contact.js",

},

output: {

path: __dirname + "/dist",

filename: "[name].bundle.js",

},

};

另外,你还可以选择打包成多个 JS 文件来将应用拆解成几个部分。像上面这样做就可以打包成三个文件:dist/home.bundle.jsdist/events.bundle.js 和 dist/contact.bundle.js

进阶自动打包

如果你正在将应用拆解,打包成多个 output 的话(如果应用的某部分有大量不需要提前加载的 JS 的话,这样做会很有用),那么在这些文件里就有可能出现重复的代码,因为在解决依赖问题的时候它们是互相不干预的。幸好,Webpack 有一个内建插件 CommonsChunk 来处理这个问题:


1

2

3

4

5

6

7

8

9

10

11


module.exports = {

// …

plugins: [

new webpack.optimize.CommonsChunkPlugin({

name: "commons",

filename: "commons.js",

minChunks: 2,

}),

],

// …

};

现在,在 output 的文件里,如果有任意模块加载了两次或更多(通过 minChunks 设置该值),它就会被打包进一个叫 commons.js 的文件里,后面你就可以在客户端缓存这个文件了。当然,这肯定会造成一次额外的请求,但是却避免了客户端多次下载相同库的问题。所以在很多场景下,这都是提升速度的举措。

开发

实际上 Webpack 有它自己的开发服务器,所以无论你正在开发一个静态网站,或者只是正在原型化前端阶段,这个服务器都是完美可用的。想要运行它,只需要在 webpack.config.js 里添加一个 devServer 对象:


1

2

3

4

5

6

7

8

9

10

11

12

13

14


module.exports = {

context: __dirname + "/src",

entry: {

app: "./app.js",

},

output: {

filename: "[name].bundle.js",

path: __dirname + "/dist/assets",

publicPath: "/assets", // New

},

devServer: {

contentBase: __dirname + "/src", // New

},

};

现在新建一个 src/index.html 文件,加入下面这行:


1

<script src="/assets/app.bundle.js"></script>

然后在命令行中,运行:


1

webpack-dev-server

服务器现在就运行在了 localhost:8080 上。注意 script 标签中的 /assets 对应的是 output.publicPath 的值 - 可以随便填成你想要的命名(如果需要一个 CDN,这就很有用了)。

当你更改 JavaScript 代码的时候,Webpack 就会实时更新页面而无需手动刷新浏览器。但是,任何对webpack.config.js 的更改都需要重启服务器才可以生效。

全局可访问方法

需要在全局命名空间里使用某些自己的方法吗?只需简单地在 webpack.config.js 里设置 output.library


1

2

3

4

5


module.exports = {

output: {

library: ‘myClassName‘,

}

};

…这样就会把打包结果绑定到一个 window.myClassName 实例上。所以使用这种命名作用域,就可以调用 entry 点里面的方法了(可以阅读文档获取更多关于这个配置的信息)。

Loaders

目前为止,我们所讲到的都是关于 JavaScript 代码的使用。从 JavaScript 代码开始是非常重要的,因为这是 Webpack 唯一使用的语言。我们可以处理任何文件类型,只要将它们传进 JavaScript 代码中。这个功能用 Loaders 来实现。

一个 loader 可以指向一个像 Sass 的预处理器,或者像 Babel 的编译器。在 NPM 中,它们通常是像 sass-loader 或babel-loader 这样命名为 *-loader

Babel + ES6

如果我们想要在项目中通过 Babel 来使用 ES6,首先要在本地正确地安装一些 loader:


1

yarn add --dev babel-loader babel-core babel-preset-es2015

…然后把它们添加进 webpack.config.js 好让 Webpack 知道哪里使用它们。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17


module.exports = {

// …

module: {

rules: [

{

test: /\.js$/,

use: [{

loader: "babel-loader",

options: { presets: ["es2015"] }

}],

},

// Loaders for other file types can go here

],

},

// …

};

一个给 Webpack 1 用户的提示:Loaders 的核心概念仍然是一样的,但语法上做了改进。在他们完成文档之前这可能不是确切的首选语法。

这样做就可以为 /\.js$/ 正则表达式寻找以 .js 结尾的文件,最后通过 Babel 编译加载。Webpack 依赖正则表达式给予你完整的控制 - 但它不会限制你的文件后缀,或者假设你的代码必须以某种特定形式组织起来。举个例子:也许你的/my_legacy_code/ 文件夹里的代码不是用 ES6 写的,那么你就可以把上面的 test 修改为/^((?!my_legacy_code).)*\.js$/,这样就可以绕过这个文件夹,其余文件用 Babel 编译。

CSS + Style Loader

如果我们只想加载应用需要的 CSS,也可以那么做。假设有一个 index.js 文件,在里面引入:


1

import styles from ‘./assets/stylesheets/application.css‘;

就会得到一个错误:You may need an appropriate loader to handle this file type。记住 Webpack 只能读取 JavaScript,所以我们必须安装正确的 loader:


1

yarn add --dev css-loader style-loader

然后在 webpack.config.js 里添加一个规则:


1

2

3

4

5

6

7

8

9

10

11

12


module.exports = {

// …

module: {

rules: [

{

test: /\.css$/,

use: ["style-loader", "css-loader"],

},

// …

],

},

};

这些 loader 会以数组逆序运行。这意味着 css-loader 会在 style-loader 之前运行。

你可能注意到甚至在生产构建的结果中,也把 CSS 打包进了 JavaScript 里面,并且 style-loader 手动地将样式写进了 <head> 中。乍一看这可能有点奇怪,但当你考虑足够多的时候就会慢慢发现这其实是有道理的。你保存了一个头部请求(在某些连接上节省宝贵的时间),并且如果你用 JavaScript 来加载 DOM,这么做基本上就消除了它自身的无样式闪屏问题。

还注意到 Webpack 已经通过把所有文件打包成一个从而自动解决了所有的 @import 查询问题(比起依赖 CSS 默认的引入导致不必要的头部请求和缓慢的资源加载,这么做显然更好)。

从 JS 里加载 CSS 相当爽,因为你可以用一种强有力的新方式去模块化 CSS 代码了。假设你只通过 button.js 加载了button.css,这就意味着如果 button.js 没有实际用到的话,它的 CSS 也不会打包进我们的生产构建结果。如果你坚持使用像 SMACSS 或者 BEM 那样的面向组件的 CSS,就会知道把 CSS 和 HTML + JavaScript 代码放更近的价值了。

CSS + Node modules

我们可以在 Webpack 里用 Node 的 ~ 前缀去引入 Node Modules。假设我们提前运行了 yarn add normalize.css,就可以这么用:


1

@import "~normalize.css";

这样就可以全面使用 NPM 来管理第三方样式库(版本及其他)而对我们而言就无需复制粘贴了。更进一步的是,Webpack 打包 CSS 比使用默认的 CSS 引入有着显而易见的优势,让客户端远离不必要的头部请求和缓慢的资源加载。

更新:这个部分和下面的部分为了更准确都进行了更新,不用再困扰于使用 CSS Modules 去简单地引入 Node Modules 了。感谢 Albert Fernández 的帮助!

CSS Modules

你可能已经听说过 CSS Modules,它将 CSS(Cascading Style Sheets)里的 C(Cascading)给提出来了。它只在用 JavaScript 构建 DOM 的时候使用有最佳效果,但本质上来说,它巧妙地将 CSS 在加载它的 JavaScript 里作用域化了(点击这个链接学习更多相关知识)。如果你计划使用它,CSS Modules 对应的 loader 是css-loaderyarn add --dev css-loader):


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15


module.exports = {

// …

module: {

rules: [

{

test: /\.css$/,

use: [

"style-loader",

{ loader: "css-loader", options: { modules: true } }

],

},

// …

],

},

};

注意:对于 css-loader 我们使用了展开的对象语法来为它添加配置。你可以写简单的字符串代表使用默认配置,style-loader 就还是这么做的。



值得注意的是实际上在使用 CSS Modules 引入 Node Modules 的时候可以去掉 ~ 符号(如@import "normalize.css";)。但是,当 @import 你自己的 CSS 时可能会遇到错误。如果你得到了 “can’t find ___” 这样的错误,尝试添加一个 resolve 对象到 webpack.config.js 里,好让 Webpack 更好地理解你预期的模块顺序。


1

2

3

4

5

6

7


const path = require("path");

module.exports = {

//…

resolve: {

modules: [path.resolve(__dirname, "src"), "node_modules"]

},

};

首先指定了我们自己的源文件目录,然后是 node_modules。这样子 Webpack 解决起来就会处理得更好一些,按照那个顺序先找我们的源文件目录,然后是已安装的 Node Modules(分别用你自己的源码和 Node Modules 目录替换其中的src 和 node_modules)。

Sass

想用 Sass?没问题,安装:


1

yarn add --dev sass-loader node-sass

然后添加另一条规则:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16


module.exports = {

// …

module: {

rules: [

{

test: /\.(sass|scss)$/,

use: [

"style-loader",

"css-loader",

"sass-loader",

]

}

// …

],

},

};

接下来当 JavaScript 调用 import 引入一个 .scss 或 .sass 文件时,Webpack 就会做它该做的事情了。

分开打包 CSS

或许你正在处理渐进式增强的网站,又或许因为其他的原因你需要一个分离的 CSS 文件。我们可以简单地实现,只需要在配置里用 extract-text-webpack-plugin 替换掉 style-loader,而无需改变其他任何代码。以 app.js 文件为例:


1

import styles from ‘./assets/stylesheets/application.css‘;

本地安装插件(我们需要这个的测试版本,2016年10月发布):


1

yarn add --dev [email protected]2.0.0-beta.4

添加到 webpack.config.js


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22


const ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {

// …

module: {

rules: [

{

test: /\.css$/,

loader: ExtractTextPlugin.extract({

loader: ‘css-loader?importLoaders=1‘,

}),

},

// …

]

},

plugins: [

new ExtractTextPlugin({

filename: "[name].bundle.css",

allChunks: true,

}),

],

};

现在运行 webpack -p 的时候就可以看到一个 app.bundle.css 文件出现在 output 目录里了。像往常一样简单地添加一个 <link> 标签到 HTML 文件里就可以了。

HTML

你可能已经猜到,Webpack 还有一个 html-loader 插件。但是,当我们开始用 JavaScript 加载 HTML 的时候,这其实是一个可以分支成不同方法的地方,而且我想不到一个单独的简单示例可以覆盖所有下一步操作的可能性。通常,你可能会在用 ReactAngularVue 或者 Ember 构建的大型系统中加载诸如 JSXMustache 或者 Handlebars 这样偏向 JavaScript 的模板 HTML;或者你可能使用一个像 Pug(以前的 Jade)或者 Haml 这样的 HTML 预处理器;或者你可能只是想简单地将源文件目录里的 HTML 复制到构建结果目录里。不管你想做什么,我没办法假设。

所以我准备在此结束本教程:你可以用 Webpack 加载 HTML,但这一点你必须自己根据你的架构做出决策,不管是我还是 Webpack 都没办法帮到你。不过使用上述例子作为参考并在 NPM 上找到正确的 loader 应该足够让你继续下去了。

从模块角度思考

为了最大程度发挥 Webpack 的作用,你不得不从模块的角度去思考(小、可复用、自包含进程),一件件事情慢慢去做好。这意味着下面这样的东西:


1

2


└── js/

└── application.js // 300KB of spaghetti code

把它变成:


1

2

3

4

5

6

7

8

9

10

11

12


└── js/

├── components/

│ ├── button.js

│ ├── calendar.js

│ ├── comment.js

│ ├── modal.js

│ ├── tab.js

│ ├── timer.js

│ ├── video.js

│ └── wysiwyg.js

└── application.js // ~ 1KB of code; imports from ./components/

结果是干净且可复用的代码。每个独立的组件取决于导入自身的依赖,并按照它想要的方式导出到其他模块。配合 Babel + ES6 使用,还可以利用 JavaScript Classes 做出更好的模块化,并且不要去想它,作用域只是在起作用。

想知道更多关于模块的内容,可以看这篇 Preethi Kasreddy 写的很棒的文章

时间: 2024-10-05 09:54:18

Webpack2入门的相关文章

##Webpack2入门教程

https://llp0574.github.io/2016/11/29/getting-started-with-webpack2/ 原文地址:https://www.cnblogs.com/letoo/p/8596432.html

【webpack2】-- 入门与解析

每次学新东西总感觉自己是不是变笨了,看了几个博客,试着试着就跑不下去,无奈只有去看官方文档. webpack是基于node的.先安装最新的node. 1.初始化 安装node后,新建一个目录,比如html5.cmd中切到当前文件夹. npm init -y 这个命令会创建一个默认的package.json.它包含了项目的一些配置参数,通过它可以进行初始安装.详细参数:https://docs.npmjs.com/files/package.json. 不要y参数的话,会在命令框中设置各项参数,但

webpack入门详解

webpack入门详解(基于webpack 3.5.4  2017-8-22) webpack常用命令: webpack --display-error-details    //执行打包 webpack -w               // 提供watch方法:实时进行打包更新 webpack -p           // 对打包后的文件进行压缩 webpack -d            // 提供source map,方便调式代码 webpack -dev-server --open 

webpack 入门2

2017年9月18日更新,添加了一个使用webpack配置多页应用的demo,可以点击此处查看 2017年8月13日更新,本文依据webpack3.5.3将文章涉及代码完全重写,所有代码都在Mac上正常运行过.希望依旧对你学习webpack有帮助. 2017年8月16号更新: 最近在Gitchat上将发起了一场关于webpack的分享,目的在于一起花最短的时间理解和学会webpack,感兴趣的童鞋可以微信扫描注册哈. webpack从入门到工程实践 写在前面的话 阅读本文之前,先看下面这个web

R语言快速上手入门

R语言快速上手入门 课程学习网址:http://www.xuetuwuyou.com/course/196 课程出自学途无忧网:http://www.xuetuwuyou.com 课程简介 本教程深入浅出地讲解如何使用R语言玩转数据.课程中涵盖R语言编程的方方面面,内容涉及R对象的类型.R的记号体系和环境系统.自定义函数.if else语句.for循环.S3类R的包系统以及调试工具等.本课程还通过示例演示如何进行向量化编程,从而对代码进行提速并尽可能地发挥R的潜能.本课程适合立志成为数据科学家的

笔记:Spring Cloud Zuul 快速入门

Spring Cloud Zuul 实现了路由规则与实例的维护问题,通过 Spring Cloud Eureka 进行整合,将自身注册为 Eureka 服务治理下的应用,同时从 Eureka 中获取了所有其他微服务的实例信息,这样的设计非常巧妙的将服务治理体系中维护的实例信息利用起来,使得维护服务实例的工作交给了服务治理框架自动完成,而对路由规则的维护,默认会将通过以服务名作为 ContextPath 的方式来创建路由映射,也可以做一些特别的配置,对于签名校验.登录校验等在微服务架构中的冗余问题

linux入门基础知识及简单命令介绍

linux入门基础知识介绍 1.计算机硬件组成介绍 计算机主要由cpu(运算器.控制器),内存,I/O,外部存储等构成. cpu主要是用来对二进制数据进行运算操作,它从内存中取出数据,然后进行相应的运算操作.不能从硬盘中直接取数据. 内存从外部存储中取出数据供cpu运存.内存的最小单位是字节(byte) 备注:由于32的cpu逻辑寻址能力最大为32内存单元.因此32位cpu可以访问的最大内存空间为:4GB,算法如下: 2^32=2^10*2^10*2^10*2^2 =1024*1024*1024

JAVA通信系列二:mina入门总结

一.学习资料 Mina入门实例(一) http://www.cnblogs.com/juepei/p/3939119.html Mina入门教程(二)----Spring4 集成Mina http://www.cnblogs.com/juepei/p/3940396.html Apache Mina 入门实例--创建一个MINA时间服务http://loftor.com/archives/apache-mina-quick-start-guide.html MINA2.0用户手册中文版--系列文

Storm入门(四)WordCount示例

Storm API文档网址如下: http://storm.apache.org/releases/current/javadocs/index.html 一.关联代码 使用maven,代码如下. pom.xml  和Storm入门(三)HelloWorld示例相同 RandomSentenceSpout.java /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor lice