查看版本:webpack -v
一、什么是webpack?
可以看做是模块打包机(一种模块化的解决方案)也是一个打包工具。
二、webpack的工作方式
把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。
image.pngWebpack 本身只能处理 JavaScript 模块,如果要处理其他类型的文件,就需要使用 loader 进行转换。
三、webpack相关文件
package.json文件:npm说明文件,里面蕴含丰富信息,包括当前项目的依赖模块,自定义的脚本任务。
在终端使用npm init命令可以自动创建这个package.json文件(输入这个命令后,终端会问你一系列诸如项目名称,项目描述,作者等信息node,如果你不准备在npm中发布你的模块,这些问题的答案都不重要,回车默认即可)
四、webpack的安装
package.json文件就绪后,在项目中安装Webpack作为依赖包
npm install -g webpack //全局安装
npm install --save-dev webpack //安装到你的项目目录
npm info webpack 可以查看webpack版本信息
运行过程中如果出现:webpack:command not found,请检查是否在全局环境下安装webpack,全局环境下安装webpack使用命令:npm install webpack -g
不推荐全局安装 webpack。这会将你项目中的 webpack 锁定到指定版本,并且在使用不同的 webpack 版本的项目中,可能会导致构建失败。 ---来自webpack官网
五、webpack搭建
1.npm install webpack --save-dev
2.npm init //初始化package.json文件
3.npm install webpack-cli --save-dev //CLI(命令行工具)已经转移到了一个单独的包webpack-cli中。
4.创建src目录并新建index.js 写入一段代码。 //webpack4.x默认是以项目根目录下的'./src/index.js'作为入口,因此我们在根目录下创建src文件夹。
function hello(str) { alert(str); }
hello('hello world!');
5.输入webpack --mode development命令或者webpack --mode production命令打包 //就可以将'./src/index.js'打包成'./dist/main.js'。
# 注意:webpack4.x的打包已经不能用webpack 文件a 文件b的方式,例如:webpack index.js bundle.js 命令
# 而是直接运行webpack --mode development或者webpack --mode production,这样便会默认进行打包,
# 入口文件是'./src/index.js', 输出路径是'./dist/main.js',
# 其中src目录即index.js文件需要手动创建,而dist目录及main.js会自动生成。
6.不过每次都要输入这个命令,非常麻烦,我们在package.json中scripts中加入两个成员:
"dev":"webpack --mode development",
"build":"webpack --mode production"
之后运行 npm run dev即可打包
7.配置其他参数
在webpack –mode production/development后加上其他参数即可例如:
webpack --mode development --watch --progress --display-modules --colors --display-reasons
当然,这也可以写入package.json的scripts之中。
六、webpack中的各种loader
1.什么是loader
用法参考:https://webpack.docschina.org/concepts/loaders/#
Loader 可以理解为是模块或资源的转换器,它本身是一个函数,接受源文件作为参数,返回转换的结果。这样,我们就可以通过 require 来加载任何类型的模块或文件,比如 CoffeeScript、 JSX、 LESS 或图片。
- loaders是你用在app源码上的转换元件。他们是用node.js运行的,把源文件作为参数,返回新的资源的函数。
- loader是文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译、压缩等,最终一起打包到指定的文件中
- 处理一个文件可以使用多个loader,loader的执行顺序是和本身的顺序是相反的,即最后一个loader最先执行,第一个loader最后执行。
- 第一个执行的loader接收源文件内容作为参数,其他loader接收前一个执行的loader的返回值作为参数。最后执行的loader会返回此模块的JavaScript源码
2.loader的安装:npm install xxx-loader -save-dev
3.loader的三种用法:
①require() (可以在 require() 引用模块的时候添加)
a.在hello.js中通过require引用style.css,执行webpack hello.js hello.bundle.js,报错如下图:
image.png
报错信息
报错提示需要一个loader转换器来处理css样式
b.输入命令:npm install css-loader style-loader --save-dev,来安装css的loader转换器和style的loader转换器
安装完成后,输入命令:webpack hello.js hello.bundle.js,进行编译hello.js
s运行发现仍然发现报错
image.png
c.查看引入style.css的地方,webpack只能处理javascript模块,处理css需要借助于loader转换器
在require() 引用模块的时候添加loader转换
那么在require引入style.css文件时,就需要css-loader转换。require('css-loader!./style.css');
image.png
在进行编译打包hello.js,编译打包成功
image.png
查看hello.bundle.js文件,多出了css样式这一块,并且css样式为一独立模块
image.png
d.在项目目录下新建一个index.html,并且引入hello.js打包后的hello.bundle.js
image.png
e.修改hello.js,运行hello()函数,接着再编译一次hello.js到hello.bundle.js
image.png
image.png
f.运行index.html,页面上弹出“hello world!”
j.但是我们发现页面的背景色并没有变成ccc的样式,要想让css样式生效,还需要在require引入css的时候使用style-loader
require('style-loader!css-loader!./style.css');
编辑完后再用webpack编译打包
image.png
image.png
h.刷新index页面,页面变成了ccc的背景色
发现style.css中的样式被使用style标签插入到了head里面,这是由style-loader实现的
css-loader是允许webpack识别.css的文件
style-loader是将webpack识别完的css文件中的内容,在编译完运行文件的时候,将这些css用style标签包起来嵌在head内
上面的例子讲述的都是在require引入模块的时候添加的loader转换,还有一种方式就是在命令行中添加loader,其他和上面讲述一样
②在配置文件webpack.config.js中通过module.loaders进行配置 (可以在 webpack 全局配置中进行绑定)
③在命令行中配置 (可以通过命令行的方式使用)
在命令行中添加loader
在命令行中输入命令:webpack hello.js hello.bundle.js --module-bind 'css=style-loader!css-loader'
(git bash中执行相当于linux,如在windows下的cmd估计要将单引号换成双引号)
去掉hello.js中require时添加的loader依赖,并将上面的命令进行编译
image.png
每次修改完文件进行编译时都需要写命令,很是繁琐,在命令最后加上--watch,当文件有变化时,就会自动编译
webpack hello.js hello.bundle.js --module-bind 'css=style-loader!css-loader' --watch
image.png
当修改hello.js文件保存后,就会看到命令行上已经重新编译
image.png
刷新index.html就可以看到修改后的内容了
七、webpack其他命令介绍:
--progress:当前打包的进度条
--display-modules:打包的模块,依赖什么而打包也会列出来
--display-reasons:打包模块的原因,因为什么打包
输入完整命令:webpack hello.js hello.bundle.js --module-bind 'css=style-loader!css-loader' --progress --display-modules --display-reasons --watch
当检测到文件有变化时进行编译,编译输出包括打包进度、打包模块、打包原因
image.png
congratulation到这里,loader的使用已经开始入门了!
八、package-lock.json到底是干嘛的?
原来package.json文件只能锁定大版本,也就是版本号的第一位,并不能锁定后面的小版本,你每次npm install都是拉取的该大版本下的最新的版本,
npm最新的版本开始提供自动生成package-lock.json功能
package-lock.json锁定依赖包版本,当用户在另外一台电脑或者新环境下,只要按照package-lock.json所标示的具体版本下载依赖库包,就能确保所有库包与你上次安装的完全一样。
这里举个例子:
"dependencies": {
"@types/node": "^8.0.33",
},
这里面的 向上标号^是定义了向后(新)兼容依赖,指如果 types/node的版本是超过8.0.33,并在大版本号(8)上相同,就允许下载最新版本的 types/node库包,例如实际上可能运行npm install时候下载的具体版本是8.0.35
那如果我们安装时的包有bug,后面需要更新怎么办?
在以前可能就是直接改package.json里面的版本,然后再npm install了,但是5版本后就不支持这样做了,因为版本已经锁定在package-lock.json里了,
所以我们只能npm install xxx@x.x.x 这样去更新我们的依赖,然后package-lock.json也能随之更新。
注意:在直接更新package.json和package-loc.json这两个文件后,npm install是可以直接覆盖掉原先的版本的,所以在协作开发时,这两个文件如果有更新,你的开发环境应该npm install一下才对。
九、前端工程项目的NODE_ENV
在package.json的scripts命令内容和webpack配置文件中可以看到NODE_ENV这个变量,它的值可以是development或product,也有人简写为'dev'或'prod'。
这个变量表示构建项目的当前环境,也就是我们的程序会跑在生产环境、测试环境还是开发环境,
node中有全局变量process表示当前node进程,process.env包含着关于系统环境的信息。但是process.env中并不存在NODE_ENV这个东西。其实NODE_ENV只是一个用户自定义的变量。
当我们在服务启动时配置NODE_ENV,或在代码中给process.env.NODE_ENV赋值,js便能通过process.env.NODE_ENV获取信息。
那么,这个变量的赋值在哪里设置呢?很多开发者将NODE_ENV=XXXX放到项目package.json的scripts命令中:
"scripts": {
"build-win": "SET NODE_ENV=production && webpack --config build/webpack.config.js",
"build": "EXPORT NODE_ENV=production && webpack --config build/webpack.config.js"
}
也有人会在webpack配置文件中对NODE_ENV作默认值处理,如果scripts.build||script.start脚本没有设置NODE_ENV,缺省值为'development'.
NODE_ENV: process.env.NODE_ENV || 'development',
不同平台下的设置区别?
在类unix系统和安装并使用了bash的windows的系统上,我们会使用:
"EXPORT NODE_ENV=production && webpack --config build/webpack.config.js"
在windows系统上,我们使用:
"SET NODE_ENV=production && webpack --config build/webpack.config.js"
有的人嫌麻烦,为了屏蔽两种系统间的这个区别,会引用第三方插件cross-env
{
"scripts": {
"build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js"
}
}
只要在NODE_ENV前面加上cross-env标志,会根据当前系统类型帮你选择适当的指令给NODE_ENV赋值。
mode选项:
在mode为production或development的状态下,为了兼顾两个状态下的程序运行,webpack创建了一个全局变量process.env.NODE_ENV,等同于在插件plugins中加入了
new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development|production") })
用来区分不同的状态,同时可以在程序中区分程序状态。
那么我们该如何在coding的时候进行区分呢?因为process.env.NODE_ENV是全局变脸给,所以可以这样来引用值,假设mode:production:
if ("development" === process.env.NODE_ENV){ .... }else{ .... }
编译之后:
if ("development" === "production"){ .... }else{ .... }
也就是最后process.env.NODE_ENV会被替换为一个常量。这个小功能可以帮助我们在写业务JS的时候,区分线上版本与开发版本。
网友评论