webpack4.0的配置及简单使用
webpack
学习 webpack
能极大的扩充前端开发视野,所以推荐前端开发工程师,使用 webpack
构建工具。
webpack 4.0
相对于之前的版本,有了更多的变化,开发速度更快,大型项目能节约 90% 的构建时间。
webpack 4.0
内置了更多的默认配置,变更了许多 API
。
webpack 的简单介绍
在面向对象的编程思想出现以前,我们都是使用面向过程的方式做网页开发的。要向页面中添加一些内容,必须要挨个创建,挨个编写内容,然后挨个添加,如果页面中的内容一多,就要编写很多雷同的代码,很容易形成代码冗余。
这个时候就出现了面向对象的编程思想,可以把页面中的内容按模块分装单独的业务逻辑文件。
面向对象要求将每个模块封装成对应的类,想要使用这个模块(如table
)时,从这个类中实例化一个对象即可,大大提高了代码的可维护性。
但是如果划分的模块很多很大,每个类要单独写在一个 JS
文件中,这样一个页面中引入的 JS
文件次数就会变多,页面会产生代码冗余,并且会增加服务器的加载负荷。而且这样加载时,无法准确的知道项目的层级关系,还是不好管理。报错不好调试。
所以我们希望,如果要在某个入口 JS
文件中使用其他 JS
文件的代码,不用将这么多的 JS
文件都引入同一个 HTML,在 JS
入口文件中自己引入其他 JS
文件,也就是 JS
文件之间可以互相引入,在 HTML
页面中只引入逻辑入口文件。
这样做的好处:
- 不需要在 HTML 中引入很多的 JS 文件,提高文件加载速度。
- 文件和文件之间的依赖关系会变得很明确,降低出错率,提高代码的可维护性。
ES6 Module 的语法可以提供这些功能:
import Header from './Header'
import Sidebar from './Sidebar'
import Content from './Content'
/*
...
*/
但是浏览器并不识别这样的语法,需要做特殊的设置。 除了可以将 <script>
标签的 type 属性 设置为 module
外,还可以使用 webpack
来解析这样的语法,解析成浏览器能识别的语法格式(webpack
不仅可以打包 JS 文件,还可以打包其他任意文件,在框架中的使用可以体现其功能的强大)。
webpack
到底是什么?
核心定义:webpack is a module bundler
。
webpack
是一个模块打包工具。
为了能让代码具备更高的复用性、可读性和维护性,我们可以将网页中的内容划分成不同的模块,使用 ES6 module
语法编写脚本,最后使用 webpack
打包工具解析 import
语法,打包 JS
脚本,生成一个可以被浏览器识别的 JS
脚本文件。
webpack
也可以识别CommonJS
模块引入规范。CMD
ADM
模块规范。
因为 webpack
是模块打包工具,所以它可以识别任何模块封装代码。
webpack
最开始只打包 JS 的模块。但是随着技术的发展,JS 可以打包任何形式的模块文件,这样的代码常出现在框架中。
webpack 环境搭建
webpack
是基于 node.js
开发的模块打包工具,它本质上是由 node
实现的,要使用 webpack
,必须先安装 Node.js
的环境。
然后在指定的项目文件目录中安装 webpack
一、npm init
会在项目的目录文件中生成一个 package.json 的项目文件,这个文件描述了这个项目的初始信息。
文件初始内容:
{
"name": "webpack-demo",
"version": "1.0.0",
"description": "",
"private": true, // 这个工具仅供自己使用,不会被发布出去
"author": "Guan Er",
"license": "ISC" // 是否开源
}
二、全局或局部安装 webpack
npm i webpack webpack-cli -g
或
npm i webpack webpack-cli --save-dev
验证 webpack
安装成功: webpack -v
一般情况下不建议全局安装 webpack
,以避免版本号变更带来的各种问题。
在项目中安装 webpack
成功之后,会在项目的目录文件下生成一个 node_modules
的文件夹,其中包含了 webpack
和其依赖包的 JS
文件。
如果是局部安装,就不能使用 webpack
命令(因为这代表全局查找 webpack
),node
提供了 npx
命令运行 webpack
。
如:npx webpack -v
;
npx
命令帮助我们在当前项目的目录中找 webpack
webpack 的简单配置
没有配置文件时也可以打包,只不过要指定打包的文件,还要在命令行写一些其他的。没有配置文件时,我们使用的是官方提供的默认配置文件。
一、基础配置
在项目的根目录中新建 webpack.config.js 做配置:
// 引入node提供的 path 对象,来配置打包好的文件的路径
const path = require('path');
// webpack 配置文件
module.exports = {
entry: './index.js', // 指定要打包的入口文件路径(根据入口文件和配置文件的相对目录自拟)
output: { // 打包好的文件的配置
filename: 'over.js', // 打包好的文件的名称
// __dirname 指 webpack.config.js 所在的目录
// mydist 文件夹的绝对路径是和 webpack.config.js 同级父目录
// 如果 path 不设置,那么打包之后的文件夹默认叫 dist,文件名默认叫 main.js
path: path.resolve(__dirname, 'mydist') // 打包好的文件的路径
}
};
以上配置文件的意义是:当在命令行输入 npx webpack
命令并执行时,会将 webpack.config.js
文件同级目录的 index.js
打包,打包之后会在 项目的根目录下生成一个 mydist
文件夹,该文件夹中包含了一个 over.js
文件,是打包之后的脚本文件,在 html
中引入的脚本是 mydist
中的 over.js
。
注:
- 当使用
npx webpack
命令打包时,要求配置文件必须叫webpack.config.js
- 如果配置文件叫其他名称(如
config.js
),还想正常打包,可以使用命令npx webpack --config config.js
一般情况下,我们的项目目录如下:
project // 根目录
node_modules // webpack 及其依赖包
dist // 打包之后的目录
index.html // 项目的结构入口
main.js // 打包之后的 js 文件,要引入到 index.html 中
src // 源代码列表
index.js
package.json
package-lock.json
webpack.config.js
####、二、利用 npm script
简化打包代码
有时候命令行的命令代码过多,执行时比较麻烦,我们可以在 package.json 中的 script 做命令配置。
在 package.json 中,找到 scripts 配置对象,可以做命令的配置
// package.json
{
...
"scripts": {
// 运行 npm run start 时,运行 package.json 中的 scripts 对象中的 start 命令,会执行 webpack命令,此处的 webpack 可以不加 npx 修饰,会默认寻找当前目录下的 webpack 命令,如果当前目录没有,再寻找全局的 webpack
"start": "webpack"
},
...
}
webpack-cli:
- 使我们在命令行中正确的运行
webpack
的命令。如果不安装这个包,就无法在命令行中使用npx webpack
这样的命令。
三、打包过程中容易出现的问题
打包时会遇到一个警告,告诉我们没有指定配置环境。
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/
需要在配置文件中指定 mode
:
module.exports = {
mode: 'production',
...
};
mode
没有设置时,底层打包时的默认值是 production
,mode
设置为 production
,打包之后的 js
文件是被压缩的,如果不想打包成压缩文件,可以将 mode
设置为 development
。
Webpack 打包示例
一、使用 Loader 打包图片
在 index.js
中引入图片:
import avatar from './1.png
会直接报错:
ERROR in ./src/1.png 1:0
Module parse failed: Unexpected character '�' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)
@ ./src/index.js 4:0-28
webpack
默认指打包 js
文件,无法打包 png
,想要实现打包,需要我们做配置。
安装一个打包图片时需要的工具:
npm i file-loader -D
然后在 webpack.config.js
配置文件中做配置:
// 引入node提供的 path 对象,来配置打包好的文件的路径
const path = require('path');
// webpack 配置文件
module.exports = {
mode: 'production',
entry: './src/index.js',
module: { // 打包非 js 文件时的配置
rules: [{
// 打包图片时,使用 file-loader 工具
test: /\.(png|gif|jpe?g)$/,
use: {
loader: 'file-loader'
}
}]
}
};
配置好之后重新打包,就不会再报错,并且在 dist 目录下,自动生成了一个新的图片。
avatar
变量就代表 dist
目录下的图片的文件名, 可以在 JS
代码中直接使用。
Loader
其实是 webpack
打包其他类型文件的解决方案。webpack
官方有非常完整的 Loader 体系,为各种类型文件的打包提供了解决方案。
1. file-loader
打包其他类型文件时的更多配置:
module.exports = {
mode: 'production',
entry: './src/index.js',
module: {
rules: [{
test: /\.(png|gif|jpe?g)$/,
use: {
loader: 'file-loader',
// 打包时的其他配置项:
options: {
// 打包之后的图片名称: 原文件名.原后缀名
name: '[name].[ext]', // placeholder 占位符配置法
outputPath: 'images/' // 设置文件打包之后的父级目录
}
}
}]
}
};
在上面的示例中,我们把 [name]
和 [ext]
称为占位符,占位符代表预留好的一些代表特殊功能的词组,类似于代码中的关键词。
webpack 官方提供的占位符里列表非常详细。
2. url-loader
先在项目中安装 url-loader
npm i url-loader -D
安装之后将 webpack.config.js 中的图片 loader 改为 url-loader,重新打包,会发现打包依旧可以成功,但是图片并没有被打包到 dist 文件夹下。
但是图片依旧正常显示。
原因是当使用 url-loader
进行打包时,webpack
会将图片打包成一个 base64
的字符串,放在 main.js
中,最终返回给 import
的变量。
这样打包的好处是不用再发送请求生成一个图片,但是也有弊端,就是当图片比较大时,生成的 base64
的字符串也会非常长。这种情况可以给当前的options
添加一个 limit
,规定 url-loader
打包的图片的最大字节数,超出这个字节数会使用 file-loader
打包。
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 1024 // 大于 1k 的图片使用 file-loader 打包
}
二、使用 Loader 打包样式文件
1. 打包 css
文件
在项目的 src
目录下新建一个 index.css
文件,在其中写入任意的 css
代码。
然后在 index.js
中通过 import
引入 css
:
...
import './index.css'
...
在 Vue
的脚手架中,这样的代码就可以直接生效,因为 Vue
脚手架底层已经对 css
的打包做了配置。我们在我们的项目中直接打包会出错,要像上面的图片打包一样,对 css
的打包做配置。
打包 css
样式文件需要使用到 style-loader
和 css-loader
,所以要先安装它们。
npm i style-loader css-loader -D
在 webpack.config.js
文件中做出配置:
module.exports = {
mode: 'production',
entry: './src/index.js',
module: {
rules: [{
test: /\.(png|gif|jpe?g)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 1024
}
}
},{
test: /\.css$/,
// 打包 css 文件时,需要两个 loader,use 要设置成数据,不能是对象
use: ['style-loader', 'css-loader']
}]
}
};
最后使用 npm run start
打包文件(这里要运行的是 package.json
中配置好的 webpack
打包命令)。
打包之后 css
样式就能生效于 html
。
css-loader
会分析出若干个 css
文件之间的关系,然后根据 css
的模块引入 @import
引入链,将若干个 css
文件合并成一段 css
代码。
可以在 src
目录下再新建一个 avatar.css
文件,然后在 index.css
中引入:
@import './avatar.css'
/*
index.css 的其他样式代码列表
*/
style-loader
会将 css-loader
生成的 css
代码挂载在页面的 <head>
标签中。
打包之后页面的 <head>
标签中就会有一对 <style>
标签,其中有所有的打包成功的 css
代码。
2. 打包 less
或 scss
文件
在项目的根目录下新建一个 index.scss
文件(可以将刚刚新建的 index.css
和 avatar.css
删除),然后写入一些 scss
代码:
body {
img {
border-radius: 50%;
}
}
将其引入到 index.js
中:
...
import './index.scss'
...
同样的,需要安装对应的 loader
(官方文档提示,打包 scss
文件时,需要安装 sass-loader
和 node-sass
两个包),然后在 webpack.config.js
中做一些配置,然后才可以对其进行打包。
npm i sass-loader node-sass -D
配置:
// 在 rules 中增加 scss 文件的打包配置
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
注:loader
的执行有严格的顺序,如果一种文件的打包需要使用到很多种 loader
,那么先执行后配置的 loader
,再执行先配置的 loader
。
3. 使用 postcss-loader
为样式自动添加样式前缀
安装:
npm i postcss-loader -D
还需要安装一个 autoprefixer
的插件:
npm i autoprefixer -D
然后在项目根目录下新建一个 postcss.config.js
,要做一些配置:
module.exports = {
plugins: [
require('autoprefixer') // postcss 要使用的一个插件
]
};
然后在 webpack.config.js
中配置:
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
'postcss-loader'
]
}
4. css-loader
的其他配置项
加入在 index.scss
中又引入了一个 header.scss
文件。
这种情况在直接打包时,不会使用经过 postcss-loader
和 sass-loader
,而直接被 css-loader
打包,如果希望 header.scss
也能按顺序被 postcss-loader
和 sass-loader
打包,那就在 css-loader
中设置 importLoaders
值,需要经过几个 Loader
,就设置几。
{
test: /\.scss$/,
use: [
'style-loader',
// 如果一个 loader 要做一些除默认配置之外的配置
// 那么在 use 中的表现形式应该是个对象
{
loader: 'css-loader',
// css-loader 的其他配置项
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
}
5. css
打包模块化
将样式直接引入 index.js
打包之后,样式会全局生效,这很容易产生问题,不同模块的样式可能会互相影响、覆盖。
webpack
提供一个 css-module
的功能,让指定样式只生效于指定结构。
src
目录列表:
header.scss
content.scss
header.js
content.js
index.js
代码:
// header.scss
.header {
width: 100%;
background: #024987;
h2 {
color: #f00
}
}
// content.scss
.content {
width: 100%;
background: #eee;
h2 {
color: #1E9FFF;
}
}
// header.js
import HeaderStyle from './header.scss'
export default function() {
var dom = document.getElementById('root');
var el = document.createElement('div');
el.className = HeaderStyle.header;
el.innerHTML = '<h2>I am header</h2>';
dom.appendChild(el);
}
// content.js
import ContentStyle from './content.scss'
export default function() {
var dom = document.getElementById('root');
var el = document.createElement('div');
el.className = ContentStyle.content;
el.innerHTML = '<h2>I am content</h2>';
dom.appendChild(el);
}
// index.js
import Header from './header'
import Content from './content'
Header();
Content();
为了能让这种样式代码按模块生效的功能打包成功,需要在 webpack.config.js
中做出相对应的配置:
{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
modules: true // 开启 css-module 功能
}
},
'sass-loader',
'postcss-loader'
]
}
6. 打包字体文件
在 src
文件夹下新建一个 font
文件夹并放入一些字体文件。
font
iconfont.eot
iconfont.svg
iconfont.ttf
iconfont.woff
在 src
下新建 index.scss
并做字体设置:
@font-face {
font-family: layui-icon;
src: url(./font/iconfont.eot?v=240);
src: url(./font/iconfont.eot?v=240#iefix) format('embedded-opentype'), url(./font/iconfont.svg?v=240#iconfont) format('svg'), url(./font/iconfont.woff?v=240) format('woff'), url(./font/iconfont.ttf?v=240) format('truetype');
}
.icon {
font-family: iconfont;
}
.icon-reply-fill:before{ content:"\e611" }
.icon-set-fill:before{ content:"\e614" }
然后在稍微修改一下 index.js
中的代码:
import Header from './header'
import Content from './content'
import IndexStyle from './index.scss'
Header();
Content();
var newEl = document.createElement('div');
newEl.classList.add(IndexStyle['icon-reply-fill']);
newEl.classList.add(IndexStyle['icon']);
document.getElementById('root').appendChild(newEl);
如果想让上面的代码能正常打包并生效,需要在 webpack.config.js
中对字体文件的打包做出配置:
// 在 rules 中新添加一个对象
{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader', // 打包字体文件需要的 file-loader
options: {
outputPath: 'font/' // 打包之后的字体文件在 dist 目录中的路径
}
}
}
然后打包项目,再运行,字体文件就能正常生效。
三、plugins 工具的简单使用
plugins
的设置能让打包过程更便捷,它相当于一个自动化打包工具,有很多打包过程如果不做配置,还是需要我们手动去修改或者书写代码,plugins
的作用就是让一些代码可以自动化的生成或修改。让 webpack
的使用变得更加便捷。
webpack
官方提供了非常完善的 plugins
体系,我们下面以 html-webpack-plugin
做示范。
一般情况下,我们在项目研发中,会有一个 HTML
源代码入口文件,项目上线时,需要上线打包之后 dist
目录中的代码。那在打包时,我们也希望在 dist
目录中自动生成一个 html
文件,其中保留源代码结构入口中的所有内容,并且还将 dist
中的脚本直接引入到这个 html
文件中。
html-webpack-plugin
就可以实现这样的功能。
可以将示例项目中的 dist
目录先删除,然后在 src
目录中新建 index.html
文件,在其中写一些初始结构代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="root"></div>
</body>
</html>
安装:
npm i html-webpack-plugin -D
配置:
// webpack.config.js
const path = require('path');
// 要是用插件,需要现在配置文件中引入
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'production',
entry: './src/index.js',
module: {...},
plugins: [new HtmlWebpackPlugin({
template: 'src/index.html' // 结构模板
})]
};
然后打包,会在 dist
目录中自动生成一个 index.html
文件,这个文件中有源代码结构文件中的所有结构代码,逻辑入口 main.js
也被直接引入其中了。
plugins
可以在 webpack
运行到某个时刻时,自动执行一些动作。
下一篇: OpenMP并行计算的使用
推荐阅读
-
哪个好?新12寸macBook与新macBook Air配置及使用体验全方位对比
-
linux top命令详解和使用实例及使用技巧(监控linux的系统状况)
-
php不使用插件导出excel的简单方法
-
iOS应用开发中矢量图的使用及修改矢量图颜色的方法
-
解析Android中string-array数据源的简单使用
-
使用Topshelf组件构建简单的Windows服务
-
Cookie的使用及保存中文并用Cookie实现购物车功能
-
Python中if elif else及缩进的使用简述
-
MyBatis 如何写配置文件和简单使用
-
Vue基于vuex、axios拦截器实现loading效果及axios的安装配置