通过npm init
命令新建一个项目:
$ npm init -y
npm init -y
Wrote to /home/deepin/Desktop/doc/webpack/demo01/package.json:
{
"name": "demo01",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
通过npm install
命令安装webpack和webpack-cli:
npm install webpack webpack-cli --save-dev
> [email protected] postinstall /home/deepin/Desktop/doc/webpack/demo01/node_modules/webpack-cli
> node ./bin/opencollective.js
Thanks for using Webpack!
Please consider donating to our Open Collective
to help us maintain this package.
Donate: https://opencollective.com/webpack/donate
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN [email protected] No description
npm WARN [email protected] No repository field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
+ [email protected]
+ [email protected]
added 390 packages from 217 contributors and audited 5231 packages in 65.573s
found 0 vulnerabilities
这里要注意的是,我是通过在项目中安装的方式来安装webpack的,而不是全局安装,这样的好处就是我们在每次执行webpack命令时都是以项目中的webapck版本为主。
webpack默认打包的文件是./src/index.js
,所以我们在项目根目录新建一个src目录,并在src目录下新建一个index.js文件:
import Hello from './hello'
alert("hello webpack...")
new Hello()
上面index.js中引入了hello.js,所以index.js所在目录下新建一个index.js文件:
export default function Hello() {
console.log('hello ...')
}
在项目根目录执行npx webpack
命令:
$ npx webpack
Hash: 9f774ffb74e02491827e
Version: webpack 4.32.2
Time: 184ms
Built at: 2019-05-23 19:40:09
Asset Size Chunks Chunk Names
main.js 955 bytes 0 [emitted] main
Entrypoint main = main.js
[0] ./src/index.js 25 bytes {0} [built]
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/
命令执行完后会在当前项目下生成dist/main.js
。main.js就是我们打包后的文件了。
在项目目录下新建一个index.html
文件,引入main.js
:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
head>
<body>
<script src="./dist/main.js">script>
body>
html>
完成上述所有操作后,在浏览器中执行该html文件,就会发现js文件中的代码被执行了。
npx webpack
如果我们在命令行中只是执行了webpack
命令,那么程序会去查找系统中安装的webpack,也就是全局安装的webpack,由于我们是局部安装的 webpack,所以通过npx
命令就能执行项目中的webpack
命令,即程序会找当前项目下的./node_modules/.bin/webpack
执行,而执行webpack
命令又需要webpack-cli
,所以也要安装webpack-cli
。
由示例程序我们知道webpack
默认打包项目目录下的./src/index.js
文件,打包后的输出文件是./dist/main.js
。那么我们如果想修改配置要怎么做呢?webpack的默认配置文件一般是webpack.config.js
,我们在项目目录下新建一个webpack.config.js
,并键入如下内容:
const path = require('path')
module.exports = {
// 指定输入文件
entry: './src/access.js',
// 指定输出文件
output: {
// 输出文件的文件名
filename: 'bundle.js',
// 输出文件路径
path: path.resolve(__dirname, "build")
}
}
重新执行webpack打包命令,我们将会看到在项目根目录生成一个build/bundle.js
。我们在index.html
中引入该文件,并在浏览器中执行,我们会发现access.js
被执行了。
我们打开打包后的文件可以看到打包的文件是被压缩了的,我们也可以在配置文件中配置mode
属性配置来指定打包是否压缩:
const path = require('path')
module.exports = {
// 配置模式
mode: 'production',
// 指定输入文件
entry: './src/access.js',
// 指定输出文件
output: {
// 输出文件的文件名
filename: 'bundle.js',
// 输出文件路径
path: path.resolve(__dirname, "build")
}
}
webpack-dev-server
提供了静态服务能力,我们通过npm
来安装:
npm install webpack-dev-server -D
通过执行webpack-dev-server
命令就可以启动服务:
$ npx webpack-dev-server
ℹ 「wds」: Project is running at http://localhost:8081/
ℹ 「wds」: webpack output is served from /
ℹ 「wds」: Content not from webpack is served from /home/deepin/Desktop/doc/webpack/demo01
ℹ 「wdm」: Hash: ee964693b814a03fffa1
Version: webpack 4.32.2
Time: 271ms
Built at: 2019-05-24 15:32:31
Asset Size Chunks Chunk Names
bundle.js 349 KiB main [emitted] main
Entrypoint main = bundle.js
[0] multi (webpack)-dev-server/client?http://localhost ./src/access.js 40 bytes {main} [built]
[./node_modules/ansi-html/index.js] 4.16 KiB {main} [built]
[./node_modules/events/events.js] 13.3 KiB {main} [built]
[./node_modules/html-entities/index.js] 231 bytes {main} [built]
[./node_modules/loglevel/lib/loglevel.js] 7.68 KiB {main} [built]
[./node_modules/node-libs-browser/node_modules/punycode/punycode.js] 14.3 KiB {main} [built]
[./node_modules/querystring-es3/index.js] 127 bytes {main} [built]
[./node_modules/url/url.js] 22.8 KiB {main} [built]
[./node_modules/webpack-dev-server/client/index.js?http://localhost] (webpack)-dev-server/client?http://localhost 9.26 KiB {main} [built]
[./node_modules/webpack-dev-server/client/overlay.js] (webpack)-dev-server/client/overlay.js 3.59 KiB {main} [built]
[./node_modules/webpack-dev-server/client/socket.js] (webpack)-dev-server/client/socket.js 1.05 KiB {main} [built]
[./node_modules/webpack-dev-server/node_modules/strip-ansi/index.js] (webpack)-dev-server/node_modules/strip-ansi/index.js 161 bytes {main} [built]
[./node_modules/webpack/hot sync ^\.\/log$] (webpack)/hot sync nonrecursive ^\.\/log$ 170 bytes {main} [built]
[./node_modules/webpack/hot/emitter.js] (webpack)/hot/emitter.js 75 bytes {main} [built]
[./src/access.js] 18 bytes {main} [built]
+ 11 hidden modules
ℹ 「wdm」: Compiled successfully.
从打印的日志中我们可以看到服务已经在http://localhost:8081/
端口启动了,在浏览器中访问该地址,就能访问到项目根目录。(注:如果项目根目录有index.html文件,会访问该文件,否则否此目录)。
我们每次启动静态服务器时都要输入npx webpack-dev-server
来启动,我们也可以自定义指定启动,类似开vue
中的npm run serve
,我们在package.json
的scripts
字段中配置"serve": "webpack-dev-server"
:
{
"name": "demo01",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
// 这里是我们配置的静态服务器
"serve": "webpack-dev-server"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.32.2",
"webpack-cli": "^3.3.2",
"webpack-dev-server": "^3.4.1"
}
}
配置好后,我们可以通过执行npm run serve
来启动静态服务。同样的我们在执行webpack
打包的时候执行的是npx webpack
,我们也能配置成npm run build
来执行打包, 如下 :
{
"name": "demo01",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"serve": "webpack-dev-server",
// 配置webpack 打包
"build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.32.2",
"webpack-cli": "^3.3.2",
"webpack-dev-server": "^3.4.1"
}
}
注:webpack.config.js
是webpack默认的配置文件名字,我们可以通过在执行webpack命令时指定使用哪个配置文件,如npx webpack --config my.config.js
。
我们可以在webpack.config.js
(webpack配置文件中)添加devServer
属性来配置静态服务器:
const path = require('path')
module.exports = {
devServer: {
// 指定启动端口
port: 9000,
// 启动时添加进度条
progress: true,
// 静态服务访问根目录
contentBase: './html/',
// 采用gzip压缩
compress: true
},
mode: 'production',
// 指定输入文件
entry: './src/access.js',
// 指定输出文件
output: {
// 输出文件的文件名
filename: 'bundle.js',
// 输出文件路径
path: path.resolve(__dirname, "build")
}
}
我们看一下这个目录contentBase: './html/',
,这个目录就是配置的当我们访问服务端口时,会访问这个目录下的index.html
文件,如果不配置这个目录的话默认访问的就是项目根目录下的index.html
文件。
npm install
$ npm installl html-webpack-plugin -D
plugins
字段中配置,template
属性指定要配置的html模块文件(要被打包的html文件),该文件会被自动引入打包后的.js
文件,filename
字段指定打包后的html
文件的名字。const path = require('path')
let HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
devServer: {
// 指定启动商品
port: 9000,
// 启动时添加进度条
progress: true,
// 静态服务访问根目录
contentBase: './html/',
// 采用gzip压缩
compress: true
},
mode: 'production',
// 指定输入文件
entry: './src/access.js',
// 指定输出文件
output: {
// 输出文件的文件名
filename: 'bundle.js',
// 输出文件路径
path: path.resolve(__dirname, "build")
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html'
})
]
}
注意:contentBase: './html/',
我们指定了静态服务器的默认访问路径是./thml/
目录,但是静态服务会优先访问HtmlWebpackPlugin
打包后的目录(注:这个目录在运行npx webpack-dev-server时并没有生成)。为了更好的理解,请看下面所示:
-项目根目录
- html
- index.html
- test.html
- build
- index.html
- bundle.js
- test.html
项目有如下目录,我们通过启动npx wepack-dev-server
并在浏览器中访问启动项目(假设项目端口为8000),也就是localhost:8000
会访问到build/index.html
,如果访问localhost:8000/bundle.js
会访问到build/bundle.js
,如果访问localhost:8000/test.html
会访问到html/test.html
,也就是说服务优先访问打包目录中文件。
我们更改一下项目中的内容,删除html/test.html
,即:
-项目根目录
- html
- index.html
- build
- index.html
- bundle.js
- test.html
我们再访问localhost:8000/test.html
就访问不到了,说明我们访问的不是打包后生成的目录,为了验证我们的说法,我们删除build
目录:
- html
- index.html
我们启动项目,我们同样做前面所示的各种访问。
// 要导入.
const HtmlWebpackPlugin = require('html-webpack-plugin')
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'main.html',
minify: {
// 除去打包后的html中的双引号操作
removeAttributeuotes: true,
// 除去打包后的html中的空白符
collapseWhitespace: true
},
// 打包后的html文件引入的打包的js后面加上hash串
hash: true
})
]
补充:我们也可以在打包生成的.js
文件名中生成hash,如下 我们在打包生成的js文件名中生成了一个截取8个字符长度的hash串(就像这样:bundle.4bf4c7f9.js):
output: {
// 输出文件的文件名
filename: 'bundle.[hash:8].js',
// 输出文件路径
path: path.resolve(__dirname, "build")
},
webapck默认只支持js
打包,如果想要配置css
等其他模块的打包需要配置模块
对应的loader
来实现。对于各个loader
的配置,是在webpack的配置文件中的module/rules
属性中配置的,如下:
module.exports = {
module: {
rules: [
]
}
}
这里用一个新的项目作演示(npm init)。
npm install html-webpack-plugin -D
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
plugins : [
new HtmlWebpackPlugin({
template: './src/index.html'
})
]
}
main.css
:@import './color.css';
body {
background: gray;
}
color.css
body {
color: whitesmoke;
}
css-loader
用于解析css语法并打包css文件,通过npm
安装css-loaer:$ npm install css-loader -D
style-loader
用来把css
文件插入到html
文件的header
标签中,安装:$ npm install style-loader -D
css-loader
和style-loader
:const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
plugins : [
new HtmlWebpackPlugin({
template: './src/index.html'
})
],
module: { // 在这下面配置loder
rules: [ // 配置loader使用规则
{
test: /\.css$/, // loader 要应用到哪些文件上,接收正则表达式
use: ["style-loader","css-loader"] // 要应用的loader,注意是从后向前执行,先解析css再插入css
}
]
}
}
index.js
和index.html
src
下新建index.js
并引入main.css
:import './main.css'
在src
下新建index.html
:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
head>
<body>
hello world!
body>
html>
npx webpack
打包npx webpack
打包,会在dist
目录下生成main.js
和index.html
两个文件,并在浏览器中运行index.html
,会看到index.html
中的header中的样式部分如下(浏览器中,不是打包生成的html):<html lang="en"><head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<style type="text/css">body {
color: whitesmoke;
}style><style type="text/css">body {
background: black;
}style>head>
<body>
hello world!
<script type="text/javascript" src="main.js">script>
body>html>
module: {
rules: [
{
test: /\.css$/,
use: [
// 对象语法
{
loader: "style-loader",
options: {
// 插入到顶部
insertAt: "top"
}
},
"css-loader"
]
}
]
}
index.html
:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<style type="text/css">
body {
background: deeppink;
}
style>
head>
<body>
hello world!
<div id="ls">
div>
body>
html>
style.less
文件body {
#ls {
width: 100px;
height: 100px;
border: 2px solid white;
}
}
index.js
中引入style.less
import "./main.css";
// 引入 less 使用import 和 require都可以
require("./style.less")
less
和less-loader
npm install less less-loader -D
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: "style-loader",
options: {
// 插入到顶部
insertAt: "top"
}
},
"css-loader"
]
},
// 对less文件的配置
{
// 配置处理less文件
test: /\.less$/,
// 从后向前执行 先执行 less-loader 再执行 css-loader 最后执行 css-loader
use: ['style-loader', 'css-loader', 'less-loader']
}
]
}