3 Webpack的正确安装方式
1、安装完node 和 git bash以后,新建文件夹webpackDemo。进入文件夹,使用npm init去初始这个项目。完成之后可以发现该命令就是生成一个package.json文件。描述了我们这个node项目的一些信息:
我们也可以去增加一些内容,比如:
private: true的意思就是我们的这个项目是一个私有的项目,不会被发布到npm的线上仓库里。
去掉"main": "index.js":因为我们的这个项目不会被外部引用,只是自己来用,没有必要向外暴露一个js文件。
2、安装Webpack有两种方式,先介绍第一种安装方式。
A. 全局安装
安装命令: npm install webpack webpack-cli -g
此时我们的webpack和webpack-cli已经安装成功了。
注意:我们不推荐通过全局的方式来安装webpack。比如说我有两个项目,假设webpack的版本号是固定的,都是4.26.0。但是我们一个项目是根据webpack3配置的,另一个项目是通过webpack4配置的,由于全局安装的webpack版本是4.26.0,根据webpack3配置的那个项目是运行不起来的。此时解决办法比较麻烦,需要删除当前的webpack4,重新安装webpakc3才能运行当前的项目。但是假设这两个项目之间有依赖,需要启动两个项目,此时全局的安装方式肯定是不能启动的。所以推荐在项目内安装Webpack。
B. 项目内安装
首先需要卸载我们之前全局安装的webpack。
卸载命令: npm uninstall webpack webpack-cli -g
卸载完成之后就可以在项目中安装webpack了,
安装命令: npm install webpack webpack-cli --save-dev 或者 npm install webpack webpack-cli -D
安装成功之后,可以发现项目中增加了node_modules文件夹,这里面保存的是webpack以及它所依赖的一些第三方的包。我们此时输入webpack -v发现找不到它的版本,这是因为node首先会去全局中找webpack,但是我们不是在全局安装的webpack。但是node提供了一个npx命令帮助我们去运行,输入:npx webpack -v,此时能够显示出版本号。这是因为npx会帮助我们去本项目中的node_modules文件夹里找webpack。
1 webpack究竟是什么?
1、之前开发网页:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<p>这是我们的网页内容</p>
<div id="root"></div>
<script src="./index.js"></script>
</body>
</html>
index.js
var dom = document.getElementById('root');
var header = document.createElement('div');
header.innerText = 'header';
dom.append(header);
var sidebar = document.createElement('div');
sidebar.innerText = 'sidebar';
dom.append(sidebar);
var content = document.createElement('div');
content.innerText = 'content';
dom.append(content);
效果:
上面这种面向过程的写法已经不能满足目前开发者的需求了,如果js的逻辑越来越多,全部放在一个文件中的这种面向过程的写法后期维护起来很麻烦。所以开始使用面向对象的编程方式来开发,上面页面中有三个部分,那我们就用三个对象来写逻辑部分:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<p>这是我们的网页内容</p>
<div id="root"></div>
<script src="./header.js"></script>
<script src="./sidebar.js"></script>
<script src="./content.js"></script>
<script src="./index.js"></script>
</body>
</html>
header.js
function Header() {
var header = document.createElement('div');
header.innerText = 'header';
dom.append(header);
}
sidebar.js
function Sidebar() {
var sidebar = document.createElement('div');
sidebar.innerText = 'sidebar';
dom.append(sidebar);
}
content.js
function Content() {
var content = document.createElement('div');
content.innerText = 'content';
dom.append(content);
}
index.js
var dom = document.getElementById('root');
new Header();
new Sidebar();
new Content();
效果一样,这样的话我们就通过面向对象改造了我们的代码,使用面向对象可以使我们的代码更具有维护性,因为不同部分的逻辑都放在各自不同部分的对象里,这样代码维护起来很方便,哪部分出错了就去那部分修改即可,这就是面向对象的优势。但是上面的写法也有一定的问题:
(1)一个html文件引用了多个js文件,导致整个页面的加载速度会变慢,因为多出了三个http请求。
(2)我们不能很直观的从index.js文件中看出不同对象所对应的文件在哪里,要想知道,我们就必须去html文件中查看。
(3)我们不能很方便的去查错。假如我们把content.js文件放在index.js后面引用,控制报错显示是index.js中有错误。
为了解决上述问题,我们可以使用webpack:
文件代码进行了一点修改:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<p>这是我们的网页内容</p>
<div id="root"></div>
<script src="./index.js"></script>
</body>
</html>
index.js
//ES Module 模块引入方式
import Header from './header.js';
import Sidebar from './sidebar.js';
import Content from './content.js';
var dom = document.getElementById('root');
new Header();
new Sidebar();
new Content();
效果:
- 首先进行npm init,创建package.json(定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等元数据)。
- 进行npm install webpack webpack-cli -D,安装webpack和webpack-cli。
- 运行npx webpack index.js,让webpack帮我们去翻译。
此时文件夹就多了一个dist文件夹,里面有一个main.js文件。但是这是页面还是报错,想要实现效果,我们需要对代码进行一点修改:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<p>这是我们的网页内容</p>
<div id="root"></div>
<script src="./dist/main.js"></script>
</body>
</html>
header.js, 另外两个模块文件也做类似的修改即可
function Header() {
var dom = document.getElementById('root');
var header = document.createElement('div');
header.innerText = 'header';
dom.append(header);
}
export default Header;
index.js
//ES Module 模块引入方式
import Header from './header.js';
import Sidebar from './sidebar.js';
import Content from './content.js';
new Header();
new Sidebar();
new Content();
此时重新运行一遍npx webpack index.js即可正常显示出效果了。
2 什么是模块打包工具?
webpack的核心定义是模块打包工具
除了上面使用的ES Module 模块引入方式以外,还有CommonJS(node里面最常用的一个模块引入规范)、CMD、AMD。webpack对以上的模块引入方式都能够正常识别。
CommonJS模块引入方式实现上面的效果:
header.js, 另外两个模块文件也做类似的修改即可
function Header() {
var dom = document.getElementById('root');
var header = document.createElement('div');
header.innerText = 'header';
dom.append(header);
}
module.exports = Header;
index.js
//ES Module 模块引入方式
// import Header from './header.js';
// import Sidebar from './sidebar.js';
// import Content from './content.js';
//CommonJS模块引入方式
var Header = require('./header.js');
var Sidebar = require('./sidebar.js');
var Content = require('./content.js');
new Header();
new Sidebar();
new Content();
重新运行npx webpack index.js之后效果一样。
webpack发展到现在,它不光能打包js文件,还能打包css文件,甚至是png等的图片文件。
4 使用webpack的配置文件
1、假如在项目中,我们想编写配置webpack的文件,可以这么做:
- 在lesson文件夹下新建一个文件,命名为:webpack.config.js。添加配置代码如下:
const path = require('path');
module.exports = {
entry: './index.js',
output: {
filename: 'bundle.js',
//__dirname指的是webpack.config.js当前所在的目录路径,第二个参数是文件夹的名字
path: path.resolve(__dirname, 'bundle')
}
}
entry: 我们这个项目要做打包的话,从哪一个项目开始打包。
output: 打包文件放置位置。这是一个对象,内部配置属性: filename:打包后文件的名字;path:打包出的文件要放在哪一个文件夹下,必须填绝对路径,而且使用前需要引入一个node的核心模块-path;
运行npx webpack,可以发现目录中多了bundle文件夹,里面有一个bundle.js文件。
此时webpack的工作流程如下:
我们运行npx webpack的时候,一开始webpack并不知道自己该如何去打包,于是它就会去找默认的配置文件,找到webpack.config.js这个文件,然后就知道了如何去打包,如何去输出。从而帮助我们去完成打包的流程。
假设我们打包配置文件不是默认名字,而是webpackconfig.js,此时执行npx webpack就会报错,因为webpack找不到默认的配置文件。解决办法:
使用这个打包命令: npx webpack --config webpackconfig.js,意思就是以webpackconfig.js为配置文件来进行打包。此时便成功打包了。
2、结合上面学习的知识点,我们对lessons这个项目进行优化。
项目中的index.js不能由浏览器直接运行,它需要webpack打包,打包后最终的代码才能在浏览器中运行。所以index.js并不是我们放在浏览器中直接运行的代码,它是我们的源代码,一般我们都是把源代码放在一个src的目录里。header.js、sidebar.js、content.js都是源代码,我们将它们都放在src文件夹里面。
目录结构:
此时我们就需要把src目录下的index.js打包成可以执行的js,那么我们就需要把配置文件做一些修改了。
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
//__dirname指的是webpack.config.js当前所在的目录路径,第二个参数是文件夹的名字
path: path.resolve(__dirname, 'dist')
}
}
此时执行npx webpack就打包成功了。问题:之前vue项目,我们都是使用npm run命令来执行一些操作的,此处确实使用npx,我们想继续使用npm run来执行,可以在scripts这么配置:
package.json文件中:
"scripts": {
"bundle": "webpack"
}
意思就是当你执行bundle这个命令,它就会自动帮你执行webpack这个命令。首先会去项目中找是否有Webpack,没有的话才会去全局找
此时输入npm run bundle就自动会帮我们进行打包了。
我们将index.html放进dist文件夹下,修改引用文件的路径之后发现此时的项目目录与之前接触的react或vue项目目录很相似了。
到目前为止,我们介绍了三种运行Webpack的方式:
我们之前安装的webpack-cli的作用就是帮助我们在命令行中正确执行webpack的指令,假设我们没有安装它,那么我们就没法在命令行里运行webpack或npx webpack这样的指令。
注意:我们不写webpack的配置文件也能打包,只不过它使用的是webpack的默认配置。但是在做工程打包的时候,每个工程它的特点和复杂度都不同,一般来说我们都需要根据工程要求自己来配置复杂的Webpack配置文件。
5 浅谈webpack打包知识点
执行npm run bundle打包之后,输出的这些命令的意思如下:
- Hash:对应的是本次打包的唯一一个Hash值
- Version:本次打包使用的webpack的版本
- Time: 本次打包所消耗的时间
- Asset:bundle.js 表示我们打包出了一个bundle.js文件
- Size: 1.36KiB 表示这个文件的大小是1.36kb
- Chunks:里面放的不仅是自己这个文件对应的id值,有可能bundle.js在大型项目中还和其它的一些js文件有关系,那么其它打包出来的js文件的id也会放到bundle.js的Chunks的字段中
- Chunk Names:和Chunks类似,只不过里面放的是每一个js文件对应的名字。此时它的值之所以是main,是因为我们配置文件中的
entry: './src/index.js'
是下面的简写方式
entry: {
main: './src/index.js'
}
- Entrypoint main 意思是打包的入口文件
- [0] ./src/index.js 323 bytes {0} [built]
[1] ./src/header.js 198 bytes {0} [built]
[2] ./src/sidebar.js 204 bytes {0} [built]
[3] ./src/content.js 204 bytes {0} [built]
意思就是打包用到的js文件 - WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'productiis value. Set 'mode' option to 'development' or 'production' to enablefor each environment.
You can also set it to 'none' to disable any default behavior. Learn m://webpack.js.org/configuration/mode/
意思是我们没有指定打包的模式以及打包的环境。消除警告的方法是添加如下配置:
const path = require('path');
module.exports = {
mode: 'production', //意思是打包后的文件被压缩,我们不配置mode的话默认值是被压缩,但是会警告。
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
mode的另一个值是development,意思就是打包后的文件不被压缩。