1.废话
作为前端菜鸟,刚开始接触webpack
时,是因为vue
,通过vue-cli
拉下来的代码,里面webpack
基本已经配置好了,需要我们自己配置的不多,一直想弄明白webpack
是怎么用的,简单记录一下,模拟vue
的目录结构,使用的webpack
和webpack-dev-server
版本也和vue
中的一样,所以这两个安装时指定了版本。一般vue
的目录结构是
2.webpack的使用
1)安装webpack
mkdir webpack-practice && cd webpack-practice // 创建并打开项目
npm init // 这时会生成一个package.json文件
npm install --save-dev [email protected] // --save-dev 开发依赖,这时会生成package-lock.js
2)创建页面及入口文件main.js
新建dist
文件夹,并创建index.html
文件,并在index.html
中引入将要被webpack
打包过来的bundle.js
文件;新建src
文件夹,并创建js
入口文件main.js
。现在的目录结构是
Document
给页面加点背景试试
// src/main.js
document.body.style.background = 'pink';
现在index.html
和main.js
还是不相关的,用webpack
将main.js
打包到dist
目录下
$ ./node_modules/.bin/webpack src/main.js dist/bundle.js
$ ./node_modules/.bin/webpack src/main.js dist/bundle.js
Hash: 9f53edbc27a012ab9184
Version: webpack 3.6.0
Time: 59ms
Asset Size Chunks Chunk Names
bundle.js 2.52 kB 0 [emitted] main
[0] ./src/main.js 50 bytes {0} [built]
这时src中就生成了一个bundle.js
文件
用浏览器直接打开看看
发现页面已经变了,说明webpack
成功将main.js
打包到bundle.js
中去了。
webpack
配置文件
在根目录新建webpack.config.js
,采用官方的配置
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/main.js',//入口文件
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
配置好了执行
$ ./node_modules/.bin/webpack
$ ./node_modules/.bin/webpack
Hash: 08e137312cf5d4feb095
Version: webpack 3.6.0
Time: 55ms
Asset Size Chunks Chunk Names
bundle.js 2.53 kB 0 [emitted] main
[0] ./src/main.js 55 bytes {0} [built]
执行这条命令会自动去寻找当前目录下的webpack.config.js
文件。通过配置文件,比之前操作起来方便多了,我们可以有更快捷的操作。
npm操作方式
我们可以使用npm start
命令来代替上述繁琐的操作,设置package.json
文件中的scripts
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack"
},
$ npm start
> [email protected] start /Users/liuzhiqin/Documents/study/webpack-practice
> webpack
Hash: 08e1373a2cf5d4feb095
Version: webpack 3.6.0
Time: 53ms
Asset Size Chunks Chunk Names
bundle.js 2.53 kB 0 [emitted] main
[0] ./src/main.js 55 bytes {0} [built]
执行这个命令会在node_modules/.bin
中寻找webpack
,无论是全局还是局部安装的webpack
,你都不需要写前面那指明详细的路径了。
3)打包css
文件
首先我们让页面的内容更丰富些,在src
中新建page.js
,并写些内容
// src/page.js
module.exports = function () {
let content = document.createElement('div');
content.textContent = 'In the begining God created the heavens and the earth';
return content;
}
入口文件是main.js
,所以要将page.js
引入到main.js
中
// src/main.js
import Page from './page';
document.body.style.background = 'pink';
document.querySelector('#app').appendChild(Page());
运行一下试试
$ npm start
> [email protected] start /Users/liuzhiqin/Documents/study/webpack-practice
> webpack
Hash: b4bcab267ae059f4e8b5
Version: webpack 3.6.0
Time: 65ms
Asset Size Chunks Chunk Names
bundle.js 3.21 kB 0 [emitted] main
[0] ./src/main.js 135 bytes {0} [built]
[1] ./src/page.js 193 bytes {0} [built]
然后看看页面
接下来我们给文字加点样式,在src
新建page.css
文件,加些样式
/* src/page.css */
#app div{
color: #333;
font-size: 30px;
font-family: fantasy;
}
同样在main.js
中引入,同时我们将背景颜色改一下
// src/main.js
import Page from './page';
import './page.css';
document.body.style.background = '#f7f7f7';
document.querySelector('#app').appendChild(Page());
运行一下试试
$ npm start
> [email protected] start /Users/liuzhiqin/Documents/study/webpack-practice
> webpack
Hash: 5d67b4883c9d13aec1e1
Version: webpack 3.6.0
Time: 65ms
Asset Size Chunks Chunk Names
bundle.js 3.77 kB 0 [emitted] main
[0] ./src/main.js 155 bytes {0} [built]
[1] ./src/page.js 193 bytes {0} [built]
[2] ./src/page.css 273 bytes {0} [built] [failed] [1 error]
ERROR in ./src/page.css
Module parse failed: /Users/liuzhiqin/Documents/study/webpack-practice/src/page.css Unexpected character '#' (2:0)
You may need an appropriate loader to handle this file type.
| /* src/page.css */
| #app div{
| color: '#fff';
| font-size: 30px;
@ ./src/main.js 3:0-19
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! [email protected] start: `webpack`
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the [email protected] start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/liuzhiqin/.npm/_logs/2018-10-19T06_24_25_011Z-debug.log
咦,怎么到page.css
那里报错了,报错信息写的很清楚,需要合适的loader
去处理这种文件类型。loader
是webpack
中用来处理不同文件的,如样式、图片、JS等资源,最后打包输出。webpack
处理css
文件需要style-loader
和css-loader
。
安装style-loader
和css-loader
$ npm install --save-dev style-loader css-loader
npm WARN [email protected] requires a peer of webpack@^4.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] No repository field.
+ [email protected]
+ [email protected]
added 42 packages from 54 contributors in 5.966s
并在webpack.config.js中配置
...
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: "style-loader"
},
{
loader: "css-loader"
}
]
},
]
}
运行一下
$ npm start
> [email protected] start /Users/liuzhiqin/Documents/study/webpack-practice
> webpack
Hash: 0c5a8f5abb63caaabad1
Version: webpack 3.6.0
Time: 393ms
Asset Size Chunks Chunk Names
bundle.js 20.6 kB 0 [emitted] main
[0] ./src/main.js 158 bytes {0} [built]
[1] ./src/page.js 193 bytes {0} [built]
[2] ./src/page.css 1.07 kB {0} [built]
[3] ./node_modules/css-loader!./src/page.css 252 bytes {0} [built]
+ 3 hidden modules
看看页面效果
4)打包scss文件
webpack
处理scss
文件和css类似。首先也是在src
目录下新建page.scss
文件,并在main.js
中引入
// src/page.scss
#app{
div{
text-align: center;
border: 1px solid red;
}
}
// src/main.js
import Page from './page';
import './page.css';
import './page.scss';
document.body.style.background = '#f7f7f7';
document.querySelector('#app').appendChild(Page());
运行一下肯定会报错
$ npm start
> [email protected] start /Users/liuzhiqin/Documents/study/webpack-practice
> webpack
Hash: e6d2ef92a954bef9d9f4
Version: webpack 3.6.0
Time: 412ms
Asset Size Chunks Chunk Names
bundle.js 21.2 kB 0 [emitted] main
[0] ./src/main.js 181 bytes {0} [built]
[1] ./src/page.js 193 bytes {0} [built]
[2] ./src/page.css 1.07 kB {0} [built]
[3] ./node_modules/css-loader!./src/page.css 252 bytes {0} [built]
[7] ./src/page.scss 263 bytes {0} [built] [failed] [1 error]
+ 3 hidden modules
ERROR in ./src/page.scss
Module parse failed: /Users/liuzhiqin/Documents/study/webpack-practice/src/page.scss Unexpected character '#' (2:0)
You may need an appropriate loader to handle this file type.
| // src/page.scss
| #app{
| div{
| text-align: center;
@ ./src/main.js 4:0-21
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! [email protected] start: `webpack`
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the [email protected] start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/liuzhiqin/.npm/_logs/2018-10-19T07_17_11_531Z-debug.log
处理scss
文件需要安装sass-loader
和node-sass
$ npm install --save-dev sass-loader node-sass
安装的那些开发依赖都可以在package.json中找到
"devDependencies": {
"css-loader": "^1.0.0",
"node-sass": "^4.9.4",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"webpack": "^3.6.0"
}
修改webpack.config.js
配置
...
module: {
rules: [
...
{//处理scss
test: /\.scss$/,
use: ["style-loader","css-loader","sass-loader"]//简化写法
}
]
}
}
再次运行一下
$ npm start
> [email protected] start /Users/liuzhiqin/Documents/study/webpack-practice
> webpack
Hash: 96acf3f989cacc7756fa
Version: webpack 3.6.0
Time: 500ms
Asset Size Chunks Chunk Names
bundle.js 22.3 kB 0 [emitted] main
[2] ./src/main.js 181 bytes {0} [built]
[3] ./src/page.js 193 bytes {0} [built]
[4] ./src/page.css 1.07 kB {0} [built]
[5] ./node_modules/css-loader!./src/page.css 252 bytes {0} [built]
[7] ./src/page.scss 1.2 kB {0} [built]
[8] ./node_modules/css-loader!./node_modules/sass-loader/lib/loader.js!./src/page.scss 222 bytes {0} [built]
+ 3 hidden modules
页面已经发生了变化
5)打包图片资源
首先在src
中新件夹image
,用于存放原始图片,然后随便找张图片放进去。webpack
处理图片需要安装url-loader
和file-loader
npm isntall --save-dev url-loader file-loader
配置webpack.config.js
,在module中加上处理图片的规则
// webpack.config.js
const path = require('path');
module.exports = {
...
module: {
rules: [
...
{//处理图片
test: /.(jpg|jpeg|png|gif|svg)$/,
use: ['url-loader?limit=8192&name=images/[name]-[hash:5].[ext]']//打包后放在images文件下,并加上哈希值命名
}
]
}
}
同时,在main.js中加引入图片
// src/main.js
import Page from './page';
import './page.css';
import './page.scss';
document.body.style.background = '#f7f7f7';
document.querySelector('#app').appendChild(Page());
let myImg = new Image();
myImg.src = require('./images/hand.jpg');
document.querySelector('#app').appendChild(myImg);
$ npm start
> [email protected] start /Users/liuzhiqin/Documents/study/webpack-practice
> webpack
Hash: a286e8bbed5798e46b43
Version: webpack 3.6.0
Time: 383ms
Asset Size Chunks Chunk Names
images/hand-a729a.jpg 106 kB [emitted]
bundle.js 22.6 kB 0 [emitted] main
[2] ./src/main.js 299 bytes {0} [built]
[3] ./src/page.js 193 bytes {0} [built]
[4] ./src/page.css 1.07 kB {0} [built]
[5] ./node_modules/css-loader!./src/page.css 252 bytes {0} [built]
[7] ./src/page.scss 1.2 kB {0} [built]
[8] ./node_modules/css-loader!./node_modules/sass-loader/lib/loader.js!./src/page.scss 222 bytes {0} [built]
[9] ./src/images/hand.jpg 67 bytes {0} [built]
+ 3 hidden modules
我们看到在dist
中生成了一个新的文件夹images
,打包后的图片也在里面,我们看看页面效果
6)webpack-dev-server
的使用
一般我们都是项目放到服务器上的,这样我们就可以实现自动刷新页面,webpack
也可以起服务的,这时需要安装webpack-dev-server
。
$ npm install --save-dev [email protected]
安装成功后,我们需要对webpack
进行配置,这时就可以放到服务器上运行了
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/main.js',//入口文件
output: {
filename: 'bundle.js',//打包后输出的文件名
path: path.resolve(__dirname, 'dist') //打包后文件存放的地方
},
...
devServer: {
contentBase: './dist'//服务指向的根目录
}
}
执行代码
$ ./node_modules/.bin/webpack-dev-server
Project is running at http://localhost:8080/
webpack output is served from /
Content not from webpack is served from ./dist
Hash: 97287251caffe518e6c6
Version: webpack 3.6.0
Time: 976ms
Asset Size Chunks Chunk Names
images/hand-a729a.jpg 106 kB [emitted]
bundle.js 348 kB 0 [emitted] [big] main
[37] multi (webpack)-dev-server/client?http://localhost:8080 ./src/main.js 40 bytes {0} [built]
[38] (webpack)-dev-server/client?http://localhost:8080 7.23 kB {0} [built]
[39] ./node_modules/url/url.js 23.3 kB {0} [built]
[45] ./node_modules/strip-ansi/index.js 161 bytes {0} [built]
[46] ./node_modules/ansi-regex/index.js 135 bytes {0} [built]
[47] ./node_modules/loglevel/lib/loglevel.js 7.86 kB {0} [built]
[48] (webpack)-dev-server/client/socket.js 1.04 kB {0} [built]
[80] (webpack)-dev-server/client/overlay.js 3.73 kB {0} [built]
[85] (webpack)/hot nonrecursive ^\.\/log$ 170 bytes {0} [built]
[87] (webpack)/hot/emitter.js 77 bytes {0} [built]
[89] ./src/main.js 301 bytes {0} [built]
[90] ./src/page.js 193 bytes {0} [built]
[91] ./src/page.css 1.07 kB {0} [built]
[94] ./src/page.scss 1.2 kB {0} [built]
[96] ./src/images/hand.jpg 67 bytes {0} [built]
+ 82 hidden modules
webpack: Compiled successfully.
在浏览器输入localhost:8080
,中看看效果
这时我们将背景改变一下,让它变回粉色试试
// src/main.js
import Page from './page';
import './page.css';
import './page.scss';
document.body.style.background = 'pink';
document.querySelector('#app').appendChild(Page());
let myImg = new Image();
myImg.src = require('./images/hand.jpg');
document.querySelector('#app').appendChild(myImg);
webpack会自动打包,并且页面自动刷新,再也不用手动刷新了。
在开发阶段,一般都是在本地起个服务,执行npm run dev
就能运行。为了效法vue
项目的目录结构,在根目录新建文件夹build
,并将webpack.config.js
移到其中,并将其重命名为webpack.dev.conf.js
。在package.json
中加上
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack",
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js"
},
执行npm run dev
试试
$ npm run dev
> [email protected] dev /Users/liuzhiqin/Documents/study/webpack-practice
> webpack-dev-server --inline --progress --config build/webpack.dev.conf.js
10% building modules 1/1 modules 0 active
Project is running at http://localhost:8080/
webpack output is served from /
Content not from webpack is served from ./dist
Hash: 53ee487180346d1f2264
Version: webpack 3.6.0
Time: 1244ms
Asset Size Chunks Chunk Names
images/hand-a729a.jpg 106 kB [emitted]
bundle.js 348 kB 0 [emitted] [big] main
[37] multi (webpack)-dev-server/client?http://localhost:8080 ./src/main.js 40 bytes {0} [built]
[38] (webpack)-dev-server/client?http://localhost:8080 7.23 kB {0} [built]
[39] ./node_modules/url/url.js 23.3 kB {0} [built]
[45] ./node_modules/strip-ansi/index.js 161 bytes {0} [built]
[46] ./node_modules/ansi-regex/index.js 135 bytes {0} [built]
[47] ./node_modules/loglevel/lib/loglevel.js 7.86 kB {0} [built]
[48] (webpack)-dev-server/client/socket.js 1.04 kB {0} [built]
[80] (webpack)-dev-server/client/overlay.js 3.73 kB {0} [built]
[85] (webpack)/hot nonrecursive ^\.\/log$ 170 bytes {0} [built]
[87] (webpack)/hot/emitter.js 77 bytes {0} [built]
[89] ./src/main.js 298 bytes {0} [built]
[90] ./src/page.js 193 bytes {0} [built]
[91] ./src/page.css 1.07 kB {0} [built]
[94] ./src/page.scss 1.2 kB {0} [built]
[96] ./src/images/hand.jpg 67 bytes {0} [built]
+ 82 hidden modules
webpack: Compiled successfully.
webpack: Compiling...
Hash: 97287251caffe518e6c6
Version: webpack 3.6.0
Time: 108ms
Asset Size Chunks Chunk Names
bundle.js 348 kB 0 [emitted] [big] main
+ 1 hidden asset
[85] (webpack)/hot nonrecursive ^\.\/log$ 170 bytes {0} [built]
[89] ./src/main.js 301 bytes {0} [built]
+ 95 hidden modules
webpack: Compiled successfully.
7)webpack
插件
vue-cli
拉下来的vue
项目中,根目录有个index.html
文件,这是个模板文件,用于生成dist
文件下面的index.html
文件,这就需要引入HtmlWebpackPlugin
插件
安装HtmlWebpackPlugin
$ npm install --save-dev html-webpack-plugin
npm WARN [email protected] requires a peer of webpack@^4.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] No repository field.
+ [email protected]
added 38 packages from 57 contributors in 8.443s
在根目录新建一个index.html
文件,里面的代码如下
Document
再次执行npm run dev
,页面同样了成功显示
$ npm run dev
> [email protected] dev /Users/liuzhiqin/Documents/study/webpack-practice
> webpack-dev-server --inline --progress --config build/webpack.dev.conf.js
10% building modules 1/1 modules 0 active
Project is running at http://localhost:8080/
webpack output is served from /
Content not from webpack is served from ./dist
Hash: d6c1b4bbf4e88618a995
Version: webpack 3.6.0
Time: 1696ms
Asset Size Chunks Chunk Names
images/hand-a729a.jpg 106 kB [emitted]
bundle.js 348 kB 0 [emitted] [big] main
index.html 389 bytes [emitted]
[37] multi (webpack)-dev-server/client?http://localhost:8080 ./src/main.js 40 bytes {0} [built]
[38] (webpack)-dev-server/client?http://localhost:8080 7.23 kB {0} [built]
[39] ./node_modules/url/url.js 23.3 kB {0} [built]
[45] ./node_modules/strip-ansi/index.js 161 bytes {0} [built]
[46] ./node_modules/ansi-regex/index.js 135 bytes {0} [built]
[47] ./node_modules/loglevel/lib/loglevel.js 7.86 kB {0} [built]
[48] (webpack)-dev-server/client/socket.js 1.04 kB {0} [built]
[80] (webpack)-dev-server/client/overlay.js 3.73 kB {0} [built]
[85] (webpack)/hot nonrecursive ^\.\/log$ 170 bytes {0} [built]
[87] (webpack)/hot/emitter.js 77 bytes {0} [built]
[89] ./src/main.js 301 bytes {0} [built]
[90] ./src/page.js 193 bytes {0} [built]
[91] ./src/page.css 1.07 kB {0} [built]
[94] ./src/page.scss 1.2 kB {0} [built]
[96] ./src/images/hand.jpg 67 bytes {0} [built]
+ 82 hidden modules
Child html-webpack-plugin for "index.html":
1 asset
[0] ./node_modules/html-webpack-plugin/lib/loader.js!./index.html 539 bytes {0} [built]
[1] ./node_modules/lodash/lodash.js 540 kB {0} [built]
[2] (webpack)/buildin/global.js 509 bytes {0} [built]
[3] (webpack)/buildin/module.js 517 bytes {0} [built]
webpack: Compiled successfully.
webpack: Compiling...
Hash: 7fd780016bdbd41a7a19
Version: webpack 3.6.0
Time: 87ms
Asset Size Chunks Chunk Names
index.html 353 bytes [emitted]
+ 2 hidden assets
[85] (webpack)/hot nonrecursive ^\.\/log$ 170 bytes {0} [built]
+ 96 hidden modules
Child html-webpack-plugin for "index.html":
1 asset
[0] ./node_modules/html-webpack-plugin/lib/loader.js!./index.html 502 bytes {1} [built]
+ 3 hidden modules
webpack: Compiled successfully.
webpack: Compiling...
Hash: c3c1881cc01ac3fc0696
Version: webpack 3.6.0
Time: 84ms
Asset Size Chunks Chunk Names
index.html 349 bytes [emitted]
+ 2 hidden assets
[85] (webpack)/hot nonrecursive ^\.\/log$ 170 bytes {0} [built]
+ 96 hidden modules
Child html-webpack-plugin for "index.html":
1 asset
[0] ./node_modules/html-webpack-plugin/lib/loader.js!./index.html 498 bytes {0} [built]
+ 3 hidden modules
webpack: Compiled successfully.
在模板文件中,没有引入bundle.js文件,HtmlWebpackPlugin
会自动添加。
其实,可以完全将dist
文件夹删掉,服务依然能正常运行,这是因为webpack-dev-server
会把打包好的数据存在内存中。现在目录结构是
这就是为什么在开发阶段时,只执行npm run dev
来启动webpack-dev-server
,那时并没有生成dist
文件夹,可以正常开发,从内存中直接加载数据。部署时,在通过命令打包(一般是npm run build
)生成dist
,然后再讲将打包好的dist
放到服务器上,再通过nginx
等web服务启动。
部署打包
在build
文件下,新建webpack.prod.conf.js
,里面的配置和webpack.dev.conf.js
很像,如下
// build/webpack.prod.conf.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/main.js',//入口文件
output: {
filename: 'bundle.js',//打包后输出的文件名
path: path.resolve(__dirname, '../dist'),//打包后文件存放的地方
},
...
devServer: {
contentBase: './dist',//服务指向的根目录
},
//webpack插件
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../index.html')
})
]
}
并更新package.json
,加上build
命令,并将start
设置为启动dev
{
...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "npm run dev",
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"build": "NODE_ENV=production webpack --progress --config build/webpack.prod.conf.js"
},
...
}
执行打包命令
$ npm run build
> [email protected] build /Users/liuzhiqin/Documents/study/webpack-practice
> NODE_ENV=production webpack --progress --config build/webpack.prod.conf.js
Hash: 4dde899e11c579299335
Version: webpack 3.6.0
Time: 971ms
Asset Size Chunks Chunk Names
images/hand-a729a.jpg 106 kB [emitted]
bundle.js 22.6 kB 0 [emitted] main
index.html 349 bytes [emitted]
[2] ./src/main.js 301 bytes {0} [built]
[3] ./src/page.js 193 bytes {0} [built]
[4] ./src/page.css 1.07 kB {0} [built]
[5] ./node_modules/css-loader!./src/page.css 252 bytes {0} [built]
[7] ./src/page.scss 1.2 kB {0} [built]
[8] ./node_modules/css-loader!./node_modules/sass-loader/lib/loader.js!./src/page.scss 254 bytes {0} [built]
[9] ./src/images/hand.jpg 67 bytes {0} [built]
+ 3 hidden modules
Child html-webpack-plugin for "index.html":
1 asset
[0] ./node_modules/html-webpack-plugin/lib/loader.js!./index.html 498 bytes {0} [built]
[2] (webpack)/buildin/global.js 509 bytes {0} [built]
[3] (webpack)/buildin/module.js 517 bytes {0} [built]
+ 1 hidden module
这时我们的根目录就会生成一个dist
文件
未完待续,菜鸟总结,希望能帮到其他新手,大神请忽略,勿喷~