关于webpack(webpack 4.0版本)

2021-02-15  本文已影响0人  codingHi

查看版本:webpack -v

一、什么是webpack?

可以看做是模块打包机(一种模块化的解决方案)也是一个打包工具。

二、webpack的工作方式

把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。

Webpack 本身只能处理 JavaScript 模块,如果要处理其他类型的文件,就需要使用 loader 进行转换。

image.png

三、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的背景色

image.png
发现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
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的时候,区分线上版本与开发版本。

上一篇下一篇

猜你喜欢

热点阅读