一、什么是webpack
是一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。可以将多种静态资源 js、css、less 转换成一个静态文件,减少了页面的请求。
二、安装和命令行
1、新建一个目录,进入目录,初始化
2、安装
全局安装
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ npm install webpack -g
在输出版本时,显示,要安装webpack-cli
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ webpack -v
The CLI moved into a separate package: webpack-cli.
Please install 'webpack-cli' in addition to webpack itself to use the CLI.
-> When using npm: npm install webpack-cli -D
-> When using yarn: yarn add webpack-cli -D
$ npm install webpack-cli -g
这样就能输出版本,可以看到我安装的是4.2.0,这里要注意,自webpack4之后,使用有很大的变化
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ webpack -v
4.2.0
局部安装
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ cnpm install webpack webpack-cli --save-dev
(1)练习(坑):处理js文件,在项目根目录下,新建hello.js,然后打包
$ webpack hello.js hello.bundle.js
Hash: e4a6ea308e8987e8d082
Version: webpack 4.2.0
Time: 556ms
Built at: 2018-3-27 11:35:19
1 asset
Entrypoint main = main.js
[0] ./hello.js 40 bytes {0} [built]
[1] multi ./hello.js hello.bundle.js 40 bytes {0} [built]
WARNING in configuration
The 'mode' option has not been set. Set 'mode' option to 'development' or 'production' to enable defaults for this environment.
ERROR in multi ./hello.js hello.bundle.js
Module not found: Error: Can't resolve 'hello.bundle.js' in 'E:\workspace\xampp\htdocs\text\webpackText'
@ multi ./hello.js hello.bundle.js
显示没有配置webpack的mode选项,默认有production和development两种,我们输入
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ webpack --mode development
Hash: f28182541f5f8d1a0d8e
Version: webpack 4.2.0
Time: 62ms
Built at: 2018-3-27 11:42:01
ERROR in Entry module not found: Error: Can't resolve './src' in 'E:\workspace\xampp\htdocs\text\webpackText'
依然有错:未找到入口模块发成错误,
这是因为webpack4.x是以项目根目录下的./src/index.js作为入口,所以我们要新建src目录且改hello.js为index.js
这里还要注意:
webpack4.x的打包已经不能用webpack 文件a 文件b
的方式,而是直接运行webpack --mode development
或者webpack --mode production
,这样便会默认进行打包,入口文件是'./src/index.js'
,输出路径是'./dist/main.js'
,其中src目录即index.js文件需要手动创建,而dist目录及main.js会自动生成。
因此我们不再按webpack 文件a 文件b
的方式运行webpack指令,而是直接运行
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ webpack --mode development
Hash: 34a98f4253e13bf8f430
Version: webpack 4.2.0
Time: 108ms
Built at: 2018-3-27 11:47:52
Asset Size Chunks Chunk Names
main.js 2.85 KiB main [emitted] main
Entrypoint main = main.js
[./src/index.js] 40 bytes {main} [built]
这样便能实现打包。
每次这样写是不是都点麻烦,我们可以在package.json中
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack --mode development"
},
每次执行就可以:
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ npm run dev // == webpack --mode development
(2)练习:处理css文件
新建一个css文件style.css,在index.js中引入
然后打包:
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ webpack --mode development
ERROR in ./src/style.css
Module parse failed: Unexpected token (1:5)
You may need an appropriate loader to handle this file type.
会报如上错误,是因为webpack不支持css文件类型,需要依赖loader
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ npm install css-loader style-loader --save-dev
css-loader:使webpack可以处理css文件
style-loader:新建一个style标签,把css-loader处理过的文件放进去,然后插入到HTML标签中
安装之后使用(直接在文件前):或者(在命令行):
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ webpack --mode development --module-bind 'css=style-loader!css-loader' // 给css绑定。。。。
那每次更新都要执行一次,有没有自动更新的???
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ webpack --mode development --module-bind 'css=style-loader!css-loader' --watch // watch参数监听,每次保存文件会自动执行
(3)其他参数:
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ webpack --mode development --module-bind 'css=style-loader!css-loader' --progress --display-modules --display-reasons
--progerss:会出现打包过程,有百分比进度条
--display-modules:会把所有打包的模块列出来
--display-reasons:会把打包的原因列出来
三、webpack的配置
(1)新建一个项目并初始化
lenovo@DESKTOP-NL309GS MINGW64 /
$ cd e:/workspace/xampp/htdocs/text/demo/webpack-demo
$ npm init
$ cnpm install webpack webpack-cli --save-dev
(2)新建一个文件webpack.config.js(默认名),是在使用webpack时默认的配置文件
单文件输入:
const path = require('path');
module.exports = {
entry: './src/js/main.js', // 入口文件
output: { // 出口文件
path: path.resolve(__dirname, 'dist/js'), // 出口文件位置,一定要是绝对路径
filename: 'bundle.js' // 出口文件名
}
}
上面:将会打包。。。main.js文件到。。。bundle.js文件
多文件输入:
const path = require('path');
module.exports = {
entry: {
main: './src/js/main.js', // 入口文件
a: './src/js/a.js'
},
output: { // 出口文件
path: path.resolve(__dirname, 'dist/js'), // 出口文件位置
filename: '[name].js' // 出口文件名,name就是entry的键名
}
}
四、自动生成HTML页面文件
(1)安装html-webpack-plugin插件
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install html-webpack-plugin --save-dev
(2)在webpack配置package.config.js中
const path = require('path');
var htmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
main: './src/js/main.js', // 入口文件
a: './src/js/a.js'
},
output: { // 出口文件
path: path.resolve(__dirname, 'dist'), // 出口文件位置
filename: 'js/[name].js' // 出口文件名
},
plugins: [
new htmlWebpackPlugin({
filename: '[name]-[hash].html', // 生成的HTML名,路径为上面output中的path
template: './index.html', // 会与根目录下的index.html相关联,把根目录下index的东西都放到生成的HTML中
inject: 'head' // 打包后的script放到head中
})
]
}
(3)传参使用
1、参数
plugins: [
new htmlWebpackPlugin({
filename: 'index.html',
template: './index.html',
title: 'hello world'
})
]
在根目录下的index.html中
<%= htmlWebpackPlugin.options.title %>
生成的dist/index.html中
hello world
2、上线地址
output: { // 出口文件
path: path.resolve(__dirname, 'dist'), // 出口文件位置
filename: 'js/[name].js', // 出口文件名,
publicPath: 'http://cdn.com/' // 上线的地址
},
在生成的index.html中
3、html压缩
title: 'hello world',
minify: {
removeComments: true, // 去掉注释
collapseWhitespace: true // 去掉空格
}
4、多页面应用,生成多个html文件
new htmlWebpackPlugin({
filename: 'main.html',
template: './index.html',
title: 'hello world',
chunks: ['main', 'a'] // 会引入main.js和a.js
}),
new htmlWebpackPlugin({
filename: 'a.html',
template: './index.html',
title: 'hello world',
excludeChunks: ['main'] // 会引入除main以外的js
})
五、loader的配置
1、解析es6语法
(1)安装babel
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install babel-loader babel-core babel-preset-env --save-dev
(2)配置webpack
module: {
rules: [
{
test: /\.js$/, // 匹配js文件
loader: 'babel-loader',
exclude: path.resolve(__dirname, 'node_modules'), // 匹配时忽略这个目录,提高打包速度
include: path.resolve(__dirname, 'src'), // 匹配时查找的范围
query: {
presets: ['env']
}
}
]
},
2、解析css
(1)安装style-loader和css-loader
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install style-loader css-loader --save-dev
(2)配置webpack
{
test: /\.css$/,
loader: 'style-loader!css-loader' // 从右到左执行,所以注意顺序
}
(3)在项目中经常有类似-webkit的前缀,每次写很麻烦,这里就要用到postcss-loader,后处理loader
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install postcss-loader autoprefixer --save-dev // autoprefixer是自动补全
配置webpack
{
test: /\.css$/,
use: [
'style-loader', // 注意顺序
{ loader: 'css-loader', options: { importLoaders: 1 } }, // 在css中使用@import引入其他文件时,
'postcss-loader' // 不加importLoaders,postcss-loader不会操作引入的文件
]
}
新建一个postcss.config.js文件和webpack.config.js同级
module.exports = {
plugins: [
require('autoprefixer')
]
}
此时,如果你打包,并不会报错,但是前缀可能也没有,所以需要在package.json中加入
"browserslist": [
"> 1%", // 全球浏览器使用率大于1%,最新两个版本并且是IE8以上的浏览器,加前缀
"last 2 versions",
"not ie <= 8"
]
3、解析less
(1)安装
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install less less-loader --save-dev
(2)webpack的配置
{
test: /\.less$/,
loader: 'style-loader!css-loader!postcss-loader!less-loader' // 不用加importLoader,less-loader默认会有
}
4、解析sass
sass的使用和less一样,只要把less改为sass就行了
5、处理html模板文件
(1)安装html-loader
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install html-loader --save-dev
(2)配置
{
test: /\.html$/,
loader: 'html-loader'
}
(3)使用
layer.js
import tpl from './layer.html';
import './layer.less';
function layer () {
return {
name: 'layer',
tpl: tpl
}
}
export default layer;
app.js
import Layer from './components/layer/layer.js';
import './css/common.css';
const App = function () {
var app = document.getElementById('app');
var layer = new Layer();
app.innerHTML = layer.tpl;
}
App();
6、使用ejs模板文件,后缀为tpl或ejs
(1)安装
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install ejs-loader --save-dev
(2)配置
{
test: /\.tpl$/,
loader: 'ejs-loader'
}
(3)使用
layer.tpl
this is <%= name %>
<% for (var i=0; i
<%= arr[i] %>
<% } %>
layer.js
import './layer.less';
import tpl from './layer.tpl'; // 返回是一个函数
function layer () {
return {
name: 'layer',
tpl: tpl
}
}
export default layer;
app.js
import Layer from './components/layer/layer.js';
import './css/common.css';
const App = function () {
var app = document.getElementById('app');
var layer = new Layer();
app.innerHTML = layer.tpl({
name: 'xueer',
arr: ['apple', 'oppo', 'xiaomi']
});
}
App();
7、用file-loader处理图片
(1)安装
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install file-loader --save-dev
(2)配置
{
test: /\.(png|jpg|gif|svg)$/i,
loader: 'file-loader'
}
(3)使用
layer.less
.layer {
width: 600px;
height: 200px;
background: url('../../assets/1.png');
div {
width: 400px;
height: 100px;
background: red;
}
.flex {
display: flex;
}
}
若是在.tpl或.ejs中使用
(4)也可以加参数
{
test: /\.(png|jpg|gif|svg)$/i,
loader: 'file-loader',
query: {
name: 'assets/[name]-[hash:5].[ext]'
}
}
8、使用url-loader处理图片(会影响文件大小)
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install url-loader --save-dev
{
test: /\.(png|jpg|gif|svg)$/i,
loader: 'url-loader',
query: {
limit: 30000, // 当图片小于30kb的时候,图片变为base64位,不打包
name: 'assets/[name]-[hash:5].[ext]'
}
}
9、通过image-webpack-loader和url-loader结合:先有image-webpack-loader打包,在通过url-loader
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install image-webpack-loader --save-dev
{
test: /\.(png|jpg|gif|svg)$/i,
loaders: [
'url-loader?limit=1000&name=assets/[name]-[hash:5].[ext]',
'image-webpack-loader'
]
}