一、 简介
只不过在 webpack 领域,所有类型的文件都可以是 module,包括 js、CSS、图片、JSON,等等
Webpack 是当下最热门的前端资源模块化管理和打包工具。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分隔,等到实际需要的时候再异步加载。通过 loader 的转换,任何形式的资源都可以视作模块,比如 CommonJs 模块、 AMD 模块、 ES6 模块、CSS、图片、 JSON、Coffeescript、 LESS 等。
二、 安装和使用
你可以在全局环境安装 webpack,也可以在项目根目录安装 webpack。在模块化盛行的当下,我推荐后者。因为 webpack 是开发环境必需的依赖,安装在全局,对它的依赖就不能写入 package.json,换个开发环境运行项目,就会出现依赖缺失的问题。
用npm初始化一个package.json文件
mkdir webpack-demo
cd webpack-demo
npm init在webpack-demo项目中安装webpack
npm install –D webpackwebpack 已经将 webpack 命令行相关的内容都迁移到 webpack-cli,所以除了 webpack 外,我们还需要安装 webpack-cli:
npm install –D webpack-cli查看webpack的版本号
Webpack –version如果在命令行直接执行webpack会怎样?
两个错误:
a. 未设定 mode,这是 webpack 4 引入的,有俩种模式,development 与 production,默认为 production - 其实还有一个隐藏的 none 模式,
b. 入口模块不存在 - webpack 4 默认从项目根目录下的 ./src/index.js 中加载入口模块,所以我们或者新建一个 src/index.js 文件,或者指定一个入口文件。在根目录下新建src/index.js文件,暂时不写内容,之后执行webpack打包
项目根目录下多了dist/main.js文件
可我们并没有指定目标位置。这也是 webpack 4 的一个变化,构建后的文件默认路径为 dist/main.js,这样我们就不必额外通过命令行或是配置文件来指定输出位置。在根目录下创建index.html,并引入打包后的文件dist/main.js
Ps:注意,我们的 script 引用的文件是 dist/main.js,而不是 index.js。这正是前端开发领域的一个趋势:开发的源文件(例子中的 index.js)与最终部署的文件(例子中的 dist/main.js)是区分开的,之所以这样,是因为开发环境与用户的使用环境并不一致。比如我们可以在开发环境使用 ES2017 甚至 ES2018 的特性,而用户的浏览器不见得支持 - 这也是 webpack 等打包工具的一个意义,它们能够辅助我们构建出在目标用户浏览器上正常运行的代码。
三、 实时刷新
在 index.html 文件中引用 dist/main.js 文件后,我们有几个问题需要解决。
a. 入口文件index.js的变化,包括它所引用的其它模块的变化如何通知给 webpack,以便重新构建 dist/main.js 文件?
b. dist/main.js 文件更新后,浏览器中打开的页面该如何自动刷新?
监控文件
第一个问题,webpack 有好几个解决办法,其中 watch 选项最直观,我们可以让 webpack 监控文件变化,一旦文件有变化,就重新构建。但默认情况下,watch 选项是禁用的。
启用watch
webpack –mode development –watch 开启监控index.js文件变化,重新构造dist/main.js刷新浏览器
至于自动刷新浏览器的问题,webpack 提供 webpack-dev-server 来解决,它是一个基于 expressjs 的开发服务器,提供实时刷新浏览器页面的功能。不过目前 webpack-dev-server 已经进入维护模式,因此,除非你想在旧浏览器上测试页面,否则请使用 webpack-serve - 全新的 webpack 开发服务器,webpack-dev-server 的继任者。
安装与使用:
webpack-dev-server是一个轻量级的服务器,修改文件源码后,自动刷新页面将修改同步到页面上
a. 全局安装
npm install webpack-dev-server -g
b. 在项目中安装并将依赖写在package.json文件中
npm install webpack-dev-server –save-dev
c. 使用命令
webpack-dev-server –hot –inline完成自动刷新
d. 默认的端口号是8080,如果需要8080端口被占用,就需要改端口
webpack-dev-server –port 3000(将端口号改为3000)
e. 启动服务
在浏览器中输入localhost:端口号
f. webpack-dev-server未刷新页面
webpack-dev-server –mode development
ps: 我们看前面 npx webpack-dev-server –mode development 的输出里有这么一行:
webpack output is served from /
是了,webpack-dev-server 构建的 main.js 其实是在 http://localhost:8080/main.js 的位置,而不是 http://localhost:8080/dist/main.js,而且,它存在于内存中,并不写入磁盘。而我们在 index.html 页面中引用的是 dist/main.js。
g. 在运行 webpack-dev-server 时指定 output.publicPath:
webpack-dev-server –mode development –output-public-path dist
h. 再次修改src/index.js文件,我们可以在 chrome 浏览器的控制台看到输出信息。
注:页面不仅自动刷新,连 index.js 都重新打包 - webpack-dev-server 一举解决我们前面提出的两个问题。
四、 webpack 配置文件
所以,webpack 4 以后,我们还需要 webpack.config.js 配置文件吗?新增的两个 mode 是否能够我们的需求?
显然,我们还会需要 webpack.config.js 配置文件。我们不妨把 webpack 4 新增的 development 与 production 两个模式看成两种普适的配置 - 我们常用、常见的配置都已经包含在其中,减小我们上手的难度,但它们不可能涵盖所有用法。
五、 webpack 与 React
安装第三方包
使用npm来安装react及react-dom
npm install react react-dom引用react.js
在index.html里添加一个div:
在index.js中写入:
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
render(){
return <div>hello webpack</div>
}
}
ReactDOM.render(,document.getElementById(‘app’));
在前面的代码中,我们用到 JSX 语法,而 webpack 并不认识它 - 此时,我们需要一个加载器。这个加载器是 babel-loader。
安装babel-loader
npm install -D babel-loader@next @babel/core @babel/preset-react创建webpack.config.js,新增如下内容 - 你看,我们这么快就用到了 webpack.config.js 文件:
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-react']
}
}
}
]
}
}
六、 图片加载器
安装file-loader
npm install –D file-loader配置webpack.config.js
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: "file-loader",
options: {}
}
]
}
- 在index.js模块汇总引用图片模块
import icon from './img/icon.png'
ReactDOM.render(<img src={icon} />, document.getElementById('root'))
七、 加载css文件
Css文件同样可以是模块,自然也有相应的加载器:
a) css-loader 预处理css文件
b) style-loader 将css插入到DOM中的style标签
注意:注意,我们如果只使用了 css-loader,则 webpack 只是将 CSS 文件预处理成模块然后打包到构建文件中,并不会插入到页面 - 这是 style-loader 的作用安装
npm install –D css-loader style-loader修改配置文件webpack.config.js
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' }
]
}
注意:loader的顺序,否则会出错
- 在index.js中引用样式文件
import ‘./index.css’;
八、 脚手架
前面的步骤里,我们几乎是一步、一步手动配置每个类型文件的加载器,一次添加一小节,然后重启 webpack-dev-server,恐怕没人喜欢这样干活。所以市面上有非常多的 boilerplates、presets 等,其中比较出名的有:
create-react-app react 官方出品的一套,只适用开发 react.js 项目;
neutrino.js 这是 Mozilla 出品的一套解决方案,Web、React、Node.js 等方案均有;
Parcel 最近新出的一套方案,零配置。
九、 打包与优化
在完成项目开发后,我们需要输出文件给生产环境部署,只要执行:
webpack –mode production
即可。具体的优化内容可以看 webpack 文档。
多数时候,我们会额外再定义一个 webpack.production.config.js 文件,针对生产环境做更细致的调整,比如分离 vendors 文件等。当然,如果你用 creat-react-app 或 neutrino.js 一类工具,通常都已经配置好了,非常方便。