webpack--介绍、安装及入门
最早的时候,所有Javascript代码都写在一个文件里面,只要加载这一个文件就够了。后来,代码越来越多,一个文件不够了,必须分成多个文件,依次加载。下面的网页代码,相信很多人都见过。
<script src="1.js"></script>
<script src="2.js"></script>
<script src="3.js"></script>
<script src="4.js"></script>
<script src="5.js"></script>
<script src="6.js"></script>
这段代码依次加载多个js文件。
这样的写法有很大的缺点。首先,加载的时候,浏览器会停止网页渲染,加载文件越多,网页失去响应的时间就会越长;其次,由于js文件之间存在依赖关系,因此必须严格保证加载顺序(比如上例的1.js要在2.js的前面),依赖性最大的模块一定要放到最后加载,当依赖关系很复杂的时候,代码的编写和维护都会变得困难。
WebPack可以看做是模块打包机
或项目自动化构建工具
:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其转换和打包为合适的格式供浏览器使用
webpack是一个前端模块化方案,更侧重模块打包,我们可以把开发中的所有资源(图片、js 文件、css 文件等)都看成模块,通过 loader(加载器)和 plugins(插件)对资源进行处理,打包成符合生产环境部署的前端资源。
js本身没有模块化的功能,后来出现commonjs支持模块化语法,webpack也支持commonjs的模块化语法,让我们可以使用模块化的方式编写js(比如require引入其他js文件),我们写的模块代码,经过webpack构建和包装之后,能够在浏览器以模块化的方式运行。
webpack不仅支持commonjs,也支持es6,amd等其他模块化语法
PS: webpack的模块不仅指js,包括css、图片等资源都可以以模块看待
自动分析项目中的各种文件,进行相应操作,比如压缩图片、js文件;预编译less,Scss等文件
方便构建各种运行环境,比如测试环境、生产环境等
Webpack的工作方式是:把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。
![](https://img.haomeiwen.com/i19225945/28362eb97d117ac0.png)
- 安装nodejs和npm:
NPM是随同NodeJS一起安装的包管理工具(安装了nodejs,会自带npm),能解决NodeJS代码部署上的很多问题,常见的使用场景有以下几种:
- 从NPM服务器下载第三方包到本地使用。
- 从NPM服务器下载并安装第三方命令行程序到本地使用。
- 将自己编写的包或命令行程序上传到NPM服务器供别人使用。
由于新版的nodejs已经集成了npm,所以之前npm也一并安装好了。同样可以通过输入 "npm -v" 来测试是否成功安装
使用以下全局安装最新版npm:
npm install npm -g
- 安装、创建并初始化项目:
首先,创建一个项目文件夹:
mkdir app
安装webpack:
全局安装webpack
npm i webpack -g
对于大多数项目,我们建议本地安装。这可以使我们在引入破坏式变更(breaking change)的依赖时,更容易分别升级项目。
初始化项目:
npm init -y
执行完后,将生产package.json
package.json定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等元数据)
也可以执行npm init,加一个-y会默认生成package.json,比如版本号,名称,包名这些会默认生成,如果没有-y,会提示你设置这些参数
使用-y默认生成后,也可以再执行npm init,手动设置各种配置参数,将会覆盖之前设置的值
然后本地安装webpack:
npm install --save-dev webpack //安装webpack
npm install --save-dev webpack-cli //4.x需要安装cli
npm list webpack---查看当前目录本地安装的webpack版本
- 简单项目样例:
打开项目文件夹
按以下结构新建项目文件:
├── dist ---打包后的目标文件存放目录
├── node_modules ---webpack本地安装的目录
├── package.json ---项目配置文件,是一个标准的npm说明文件
├── webpack.config.js ---webpack配置文件
└── src
└── app.js ---源码存放目录
webpack.config.js需要自己新建,内容类似于:
module.exports = {
entry:'./src/app.js',
output:{
filename:'app.bundle.js'
}
}
entry是源文件,需要指定目录,output是打包后的文件,打包后的文件会自动放到dist里,不需要指定目录
进入项目,执行命令:
webpack
完成打包
webpack --watch:源文件改变后不需要重新打包,目标文件会自动改变
webpack -d:测试版,不会压缩js,加入调试信息可以方便在浏览器调试(调试的时候可以自动关联到源码,可以在源码里断点调试) 默认情况下不带参数会生成生产版,生成版会压缩
我们可以把webpack命令集成到package.json里面,这样就可以用npm命令来执行打包(一般推荐这么做)
在package.json的scripts模块里加入webpack命令的配置:
"scripts": {
"dev": "webpack -d --watch",
"prod": "webpack"
},
执行npm run dev---打包生产调试版
执行npm run prod---打包生产版
- 项目样例2:
在项目中创建两个文件夹,app文件夹和public文件夹(跟之前的src和dist一样),app文件夹用来存放原始数据和我们将写的JavaScript模块,public文件夹用来存放之后供浏览器读取的文件(包括使用webpack打包生成的js文件以及一个index.html文件)。接下来我们再创建三个文件:
index.html --放在public文件夹中;
Greeter.js-- 放在app文件夹中;
main.js-- 放在app文件夹中;
此时项目结构如下图所示
![](https://img.haomeiwen.com/i19225945/53a7c61d5725e27a.png)
我们在index.html文件中写入最基础的html代码,它在这里目的在于引入打包后的js文件(这里我们先把之后打包后的js文件命名为bundle.js,之后我们还会详细讲述)。
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Webpack Sample Project</title>
</head>
<body>
<div id='root'>
</div>
<script src="bundle.js"></script>
</body>
</html>
我们在Greeter.js中定义一个返回包含问候信息的html元素的函数,并依据CommonJS规范导出这个函数为一个模块:
// Greeter.js
module.exports = function() {
var greet = document.createElement('div');
greet.textContent = "Hi there and greetings!";
return greet;
};
main.js文件中我们写入下述代码,用以把Greeter模块返回的节点插入页面。
//main.js
const greeter = require('./Greeter.js');
document.querySelector("#root").appendChild(greeter());
webpack.config.js:
webpack.config.js:
module.exports = {
entry: __dirname + "/app/main.js",
output: {
path: __dirname + "/public",//打包后的文件存放的地方
filename: "bundle.js"//打包后输出文件的文件名
}
}
注:“__dirname”是node.js中的一个全局变量,它指向当前执行脚本所在的目录。
package.json:
{
"name": "app6",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"webpack-cli": "^3.2.3",
"webpack": "^4.29.5"
},
"devDependencies": {},
"scripts": {
"start": "webpack",
"debug":"webpack -d"
},
"keywords": [],
"author": "",
"license": "ISC"
}
start命令可以用npm start(也可以npm run start),其他命令必须是npm run xxx,比如npm run debug
- html-webpack-plugin插件
前面的例子中, index.html 文件太死了,连 js 文件都写死了,有时候引用的 js 文件是动态变化的呢?
打个比方,类似下面这种例子:
<script src="app.bundle1.js"></script>
<script src="app.bundle2.js"></script>
<script src="app.bundle3.js"></script>
而且还不确定有多少个。
还有一种情况,有时候为了更好的 cache 处理,文件名还带着 hash,例如下面这样:
main.9046fe2bf8166cbe16d7.js
这个 hash 是文件的 md5 值,随着文件的内容而变化,你总不能每变化一次,就改一下 index.html 文件吧?
效率太低!
下面我们要使用一个 webpack 的插件 html-webpack-plugin 来更好的处理这个问题。
webpack 吸引人的地方就是因为它有太多的插件,有时候一些需求,一个插件就搞定。
安装html-webpack-plugin插件:
npm install html-webpack-plugin --save-dev
安装成功后,package.json 这个文件会多出一行 "html-webpack-plugin": "^x.xx.x",,如下所示:
{
"name": "hello-wepback",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack -d --watch",
"prod": "webpack -p"
},
"author": "",
"license": "ISC",
"devDependencies": {
"html-webpack-plugin": "^2.30.1",
"webpack": "^3.8.1"
}
}
也可以反向操作,先配置好devDependencies,然后在工程目录执行:
npm install
这样可以批量安装devDependencies里所有配置的依赖
现在我们把第一个例子中生成的 index.html 先删除掉,我们要用 html-webpack-plugin 这个插件来自动生成它。
把 webpack.config.js 文件改一下,如下所示:
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/app.js',
output: {
path: __dirname + '/dist',
filename: 'app.bundle.js'
},
plugins: [new HtmlWebpackPlugin()]
};
然后运行
npm run start
就会自动生成index.html
<html>
<head>
<meta charset="UTF-8">
<title>Webpack App</title>
</head>
<body>
<script type="text/javascript" src="app.bundle.js"></script></body>
</html>
跟手动写的一样
连标题 <title>Webpack App</title> 都自动生成了,如果这是固定的话,就不太灵活,但是 html-webpack-plugin 有选项来处理这个问题。
要改变 title 很简单,上文提到 HtmlWebpackPlugin 这个方法可以传入很多参数的,下面这样就可以解决这个问题。
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/app.js',
output: {
path: __dirname + '/dist',
filename: 'app.bundle.js'
},
plugins: [new HtmlWebpackPlugin({
title: "hello world"
})]
};
只是改变了一点点东西,其实也没多大用处,有时候我们要让 index.html 根据我们的意愿来生成。就是说它的内容是我们自己定的。
这个就不得不提到 html-webpack-plugin 的 template 功能。
把 webpack.config.js 更改如下:
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/app.js',
output: {
path: __dirname + '/dist',
filename: 'app.bundle.js'
},
plugins: [new HtmlWebpackPlugin({
template: './src/index.html',
})]
};
接着新建 src/index.html 文件,内容如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello World</title>
</head>
<body>
</body>
</html>
我们再来看看新生成的 dist/index.html 文件,内容如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello World</title>
</head>
<body>
<script type="text/javascript" src="app.bundle.js"></script></body>
</html>
下面我再来介绍几个参数,以及它的结果。
filename: 'index.html' :默认情况下生成的 html 文件叫 index.html,但有时候你不想叫这个名字,可以改。
minify: {
collapseWhitespace: true,
},
这个可以把生成的 index.html 文件的内容的没用空格去掉,减少空间。(默认是true,可以改成false,这样就会按正常的格式生成html)
hash: true :为了更好的 cache,可以在文件名后加个 hash。
效果如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Webpack App</title>
<meta name="viewport" content="width=device-width,initial-scale=1"></head>
<body>
<script src="bundle.js?4abc2d79d055a2c3cf3f"></script></body>
</html>
最终的配置文件可能如下:
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/app.js',
output: {
path: __dirname + '/dist',
filename: 'app.bundle.js'
},
plugins: [new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
minify: {
collapseWhitespace: true,
},
hash: true,
})]
};