npm init -y
npm i webpack webpack-cli
\test01\package.json :加入启动简化的命令
{
"name": "test01",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
},
"devDependencies": {
"raw-loader": "^4.0.1"
}
}
新建webpack.config.js的webpack的配置文件。
测试一下环境:
\test01\src\data\test.txt
测试数据
\test01\src\test.js
import data from './data/test.txt';
console.log(data);
\test01\html\1.test.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<script src="../dist/test.js">script>
body>
html>
\test01\webpack.config.js
const path = require('path');
module.exports = {
mode: 'development',
entry: {
'test': './src/test.js',
},
output: {
// 这个路径是默认会被加入 devServer 的 contentBase 中
path: path.resolve(__dirname, 'dist'),
filename: "[name].js"
},
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
}
]
},
};
npm install --save-dev raw-loader
npm start
测试成功!
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.19
Branch: branch01commit description:a0.19(Webpack03配置并测试Webpack环境)
tag:a0.19
扩展 webpack
本身的一些功能,它们会运行在各种模块解析完成以后(相当于loader
解析完成后,在打包编译之前)的打包编译阶段,比如对解析后的模块文件进行压缩等都可以利用插件的形式进行实现。
在打包结束后,⾃动生成⼀个 html
文件,并把打包生成的 js
模块引⼊到该 html
中,其实在上一篇当中提过,如Vue、React
的模板文件放在当前的html
的文件夹中,其实我们最终的希望的是src
目录下的所有模块全部打包放在dist
目录下,同时html
文件下的文件们也放入在dist
目录下,这样所有需要在服务器上运行的文件我们都通通都组织在dist
目录下了,而不再是分散在各个文件夹下了,然后一个个去组织,这样太麻烦了,我们就可以通过当前插件的方式做到这种效果。
HtmlWebpackPlugin
简化了HTML文件的创建,以便为你的webpack包提供服务。这对于在文件名中包含每次会随着编译而发生变化哈希的webpack bundle
尤其有用。 你可以让插件为你生成一个HTML
文件,使用lodash模板提供你自己的模板,或使用你自己的loader。
npm install --save-dev html-webpack-plugin
// webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
...
plugins: [
new HtmlWebpackPlugin({
title: "My App",
filename: "app.html",
template: "./src/html/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><%=htmlWebpackPlugin.options.title%>title>
head>
<body>
<h1>html-webpack-pluginh1>
body>
html>
在 html
模板中,可以通过 <%=htmlWebpackPlugin.options.XXX%>
的方式获取配置的值
更多的配置
title
: ⽤来生成⻚面的 title
元素filename
: 输出的 HTML
⽂件名,默认是 index.html
, 也可以直接配置子目录template
: 模板⽂件路径,⽀持加载器(loader
),⽐如 html!./index.html
inject
: true | 'head' | 'body' | false
,注⼊所有的资源到特定的 template
或者 templateContent
中,如果设置为 true
或者 body
,所有的 javascript
资源将被放置到 body
元素的底部(默认注入在body里),'head'
将放置到 head
元素中favicon
: 添加特定的 favicon
路径到输出的 HTML
文件中minify
: {} | false
, 传递 html-minifier
选项给 minify
输出hash
: true | false
,如果为 true
,将添加 webpack
编译生成的 hash
到所有包含的脚本和 CSS
⽂件,对于解除 cache
很有用cache
: true | false
,如果为 true
,这是默认值,仅在文件修改之后才会发布文件showErrors
: true | false
,如果为 true
,这是默认值,错误信息会写入到 HTML
⻚面中chunks
: 允许只添加某些块 (⽐如,仅 unit test 块)chunksSortMode
: 允许控制块在添加到⻚面之前的排序方式,⽀持的值:'none' | 'default' |{function}-default:'auto'
excludeChunks
: 允许跳过某些块,(⽐如,跳过单元测试的块)HtmlWebpackPlugin应用。
安装插件
npm install --save-dev html-webpack-plugin
\test01\src\template.js
console.log('template');
通常在这里我们需要引用template.js文件,这里我们完全利用webpack去处理。
\test01\html\template.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
body>
html>
\test01\webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: 'development',
entry: {
// 'test': './src/test.js',
'template': './src/template.js'
},
output: {
// 这个路径是默认会被加入 devServer 的 contentBase 中
path: path.resolve(__dirname, 'dist'),
filename: "[name].js"
},
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
// 模板文件存放的目录
template: "./html/template.html",
// 生成(打包)后的html存放目录
filename: "app.html"
}),
],
};
npm start
打包后,我们看dist
目录,首先template.js
被移动过来了,template.html
重命名为app.html
被移动过来了。
生成后的app.html
会自动帮助我们插入script
标签,src
则自动引入入口文件(打包后的template.js
,设置几个入口文件就会一并打包进去),插件就帮助我们处理,我们无需处理,因此项目中的往html
引入css
、js
都可通过这种方式进行处理。
模板是不需要进行模块化处理的,所有没有放入loader
里处理,而是在最后所有loader
处理完毕,模块解析完毕后,紧接着在输出的时候把该文件带着一起输出过去了。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<script src="template.js">script>body>
html>
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.20
Branch: branch01commit description:a0.20(Webpack03——example01-1使用HtmlWebpackPlugin插件生成html自动引入js)
tag:a0.20
假设有多个html
模板(不止一个首页),怎么弄?仔细观察文档的配置项,**filename
和template
**都是字符串类型,既不是数组也不是对象,配置项肯定是不允许多个html
的,仅能代表一个,除非支持逗号分隔。
我们尝试一下:
可以参考一下官网
以上是配置项没做过多说明,但是下面demo中就有说明:
Generating Multiple HTML Files
To generate more than one HTML file, declare the plugin more than once in your plugins array
要生成多个HTML文件,请在插件数组中多次声明该插件
webpack.config.js
{
entry: 'index.js',
output: {
path: __dirname + '/dist',
filename: 'index_bundle.js'
},
plugins: [
new HtmlWebpackPlugin(), // Generates default index.html
new HtmlWebpackPlugin({ // Also generate a test.html
filename: 'test.html',
template: 'src/assets/test.html'
})
]
}
\test01\html\template1.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
body>
html>
\test01\webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: 'development',
entry: {
// 'test': './src/test.js',
'template': './src/template.js'
},
output: {
// 这个路径是默认会被加入 devServer 的 contentBase 中
path: path.resolve(__dirname, 'dist'),
filename: "[name].js"
},
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
// 模板文件存放的目录
template: "./html/template.html",
// 生成(打包)后的html存放目录
filename: "app.html"
}),
new HtmlWebpackPlugin({
// 模板文件存放的目录
template: "./html/template1.html",
// 生成(打包)后的html存放目录
filename: "app1.html"
}),
],
};
npm start
\test01\dist\app1.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<script src="template.js">script>body>
html>
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.21
Branch: branch01commit description:a0.21(Webpack03——example01-2使用HtmlWebpackPlugin插件生成多个html自动引入js)
tag:a0.21
除此之外,还可以往模板中注入变量,即往模板中注入数据(具体参考3.1
注入说明),如设置一个title
,可在模板中使用该变量作为标题
。
\test01\webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: 'development',
// mode: 'production',
entry: {
// 'test': './src/test.js',
'template': './src/template.js'
},
output: {
// 这个路径是默认会被加入 devServer 的 contentBase 中
path: path.resolve(__dirname, 'dist'),
filename: "[name].js"
},
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: "My App",
// 模板文件存放的目录
template: "./html/template.html",
// 生成(打包)后的html存放目录
filename: "app.html"
})
],
};
\test01\html\template.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title><%=htmlWebpackPlugin.options.title%>title>
head>
<body>
body>
html>
npm start
\test01\dist\app.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Apptitle>
head>
<body>
<script src="template.js">script>body>
html>
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.22
Branch: branch01commit description:a0.22(Webpack03——example01-3使用HtmlWebpackPlugin插件引入title变量)
tag:a0.22
在 html
模板中,可以通过 <%=htmlWebpackPlugin.options.XXX%>
的方式获取配置的值
更多的配置
title
: ⽤来生成⻚面的 title
元素filename
: 输出的 HTML
⽂件名,默认是 index.html
, 也可以直接配置子目录template
: 模板⽂件路径,⽀持加载器(loader
),⽐如 html!./index.html
inject
: true | 'head' | 'body' | false
,注⼊所有的资源到特定的 template
或者 templateContent
中,如果设置为 true
或者 body
,所有的 javascript
资源将被放置到 body
元素的底部(默认注入在body
里),'head'
将放置到 head
元素中favicon
: 添加特定的 favicon
(网页图标) 路径到输出的 HTML
文件中minify
(压缩): {} | false
, 传递 html-minifier
选项给 minify
输出hash
: true | false
,如果为 true
,将添加 webpack
编译生成的 hash
到所有包含的脚本和 CSS
⽂件,对于解除 cache
很有用cache
: true | false
,如果为 true
,这是默认值,仅在文件修改之后才会发布文件showErrors
: true | false
,如果为 true
,这是默认值,错误信息会写入到 HTML
⻚面中chunks
: 允许只添加某些块 (⽐如,仅 unit test 块)chunksSortMode
: 允许控制块在添加到⻚面之前的排序方式,⽀持的值:'none' | 'default' |{function}-default:'auto'
excludeChunks
: 允许跳过某些块,(⽐如,跳过单元测试的块)压缩html
If the minify
option is set to true
(the default when webpack’s mode
is 'production'
), the generated HTML will be minified using html-minifier-terser and the following options:
如果将minify选项设置为true(当webpack的模式为“生产”时为默认值),则将使用html-minifier-terser和以下选项来缩小生成的HTML:
{
collapseWhitespace: true, // 折叠有助于文档树中文本节点的空白
removeComments: true, // 删除HTML注释
removeRedundantAttributes: true, // 当值匹配默认值时删除属性。
removeScriptTypeAttributes: true, // type="text/javascript"从script标签中删除。其他type属性值保持不变
removeStyleLinkTypeAttributes: true, // type="text/css"从style和link标签中删除。其他type属性值保持不变
useShortDoctype: true // doctype用短(HTML5)文档类型替换
}
To use custom html-minifier options pass an object to minify
instead. This object will not be merged with the defaults above.
要使用自定义html-minifier选项,请通过传递一个对象来缩小。该对象不会与上面的默认值合并。
To disable minification during production mode set the minify
option to false
.
要在生产模式下禁用压缩,请将minify选项设置为false。
安装
npm install html-minifier-terser
demo01\webpack-demo02\webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: 'development',
entry: {
// 'test': './src/test.js',
'template': './src/template.js'
},
output: {
// 这个路径是默认会被加入 devServer 的 contentBase 中
path: path.resolve(__dirname, 'dist'),
filename: "[name].js"
},
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: "My App",
// 模板文件存放的目录
template: "./html/template.html",
// 生成(打包)后的html存放目录
filename: "app.html",
minify: {
collapseWhitespace: true, // 折叠有助于文档树中文本节点的空白
removeComments: true, // 删除HTML注释
removeRedundantAttributes: true, // 当值匹配默认值时删除属性。
removeScriptTypeAttributes: true, // type="text/javascript"从script标签中删除。其他type属性值保持不变
removeStyleLinkTypeAttributes: true, // type="text/css"从style和link标签中删除。其他type属性值保持不变
useShortDoctype: true // doctype用短(HTML5)文档类型替换
},
}),
// new HtmlWebpackPlugin({
// // 模板文件存放的目录
// template: "./html/template1.html",
// // 生成(打包)后的html存放目录
// filename: "app1.html"
// }),
],
};
npm start
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.23
Branch: branch01commit description:a0.23(Webpack03——example01-4-demo使用HtmlWebpackPlugin插件配置minify=>压缩html文件)
tag:a0.23
如果想在dist
下将js
输出到另一个目录:
output: {
// 这个路径是默认会被加入 devServer 的 contentBase 中
path: path.resolve(__dirname, 'dist/js'),
filename: "[name].js"
}
output
中设置的path
可能会影响后续的loader
及plugins
中所有打包输出的路径,即很多情况下loader
及plugins
都以Webpack
中的output
中的path
为基准路径,这点尤为重要,小心出错。
如果想输出不同的路径,我们再filename
就行配置。
\test01\webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: 'development',
entry: {
// 'test': './src/test.js',
'template': './src/template.js'
},
output: {
// 这个路径是默认会被加入 devServer 的 contentBase 中
path: path.resolve(__dirname, 'dist'),
// filename: "[name].js"
filename: "./public/js/[name].js"
},
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: "My App",
// 模板文件存放的目录
template: "./html/template.html",
// 生成(打包)后的html存放目录
filename: "app.html",
minify: {
collapseWhitespace: true, // 折叠有助于文档树中文本节点的空白
removeComments: true, // 删除HTML注释
removeRedundantAttributes: true, // 当值匹配默认值时删除属性。
removeScriptTypeAttributes: true, // type="text/javascript"从script标签中删除。其他type属性值保持不变
removeStyleLinkTypeAttributes: true, // type="text/css"从style和link标签中删除。其他type属性值保持不变
useShortDoctype: true // doctype用短(HTML5)文档类型替换
},
}),
// new HtmlWebpackPlugin({
// // 模板文件存放的目录
// template: "./html/template1.html",
// // 生成(打包)后的html存放目录
// filename: "app1.html"
// }),
],
};
npm start
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.24
Branch: branch01commit description:a0.24(Webpack03——example01-5-使用HtmlWebpackPlugin插件配置文件的自定义dist下的目录)
tag:a0.24
注意:使用框架react、vue、angular都会基础配置默认配置好(脚手架工具)。
删除(清理之前的构建目录)构建目录
npm install --save-dev clean-webpack-plugin
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports = {
...
plugins: [
...,
new CleanWebpackPlugin(),
...
]
}
\test01\webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports = {
mode: 'development',
entry: {
// 'test': './src/test.js',
'template': './src/template.js'
},
output: {
// 这个路径是默认会被加入 devServer 的 contentBase 中
path: path.resolve(__dirname, 'dist'),
// filename: "[name].js"
filename: "./public/js/[name].js"
},
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: "My App",
// 模板文件存放的目录
template: "./html/template.html",
// 生成(打包)后的html存放目录
filename: "app.html",
minify: {
collapseWhitespace: true, // 折叠有助于文档树中文本节点的空白
removeComments: true, // 删除HTML注释
removeRedundantAttributes: true, // 当值匹配默认值时删除属性。
removeScriptTypeAttributes: true, // type="text/javascript"从script标签中删除。其他type属性值保持不变
removeStyleLinkTypeAttributes: true, // type="text/css"从style和link标签中删除。其他type属性值保持不变
useShortDoctype: true // doctype用短(HTML5)文档类型替换
},
}),
// new HtmlWebpackPlugin({
// // 模板文件存放的目录
// template: "./html/template1.html",
// // 生成(打包)后的html存放目录
// filename: "app1.html"
// }),
new CleanWebpackPlugin(),
],
};
npm start
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.25
Branch: branch01commit description:a0.25(Webpack03——example02-使用clean-webpack-plugin插件删除(清理之前的构建目录)构建目录)
tag:a0.25
提取 CSS
到一个单独的文件中
npm install --save-dev mini-css-extract-plugin
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
...,
module: {
rules: [
{
test: /\.s[ac]ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
'css-loader',
'sass-loader'
]
}
]
},
plugins: [
...,
new MiniCssExtractPlugin({
filename: '[name].css'
}),
...
]
}
\test01\src\css\index.css
body {
background: red;
}
\test01\src\template.js
import './css/index.css';
console.log('template');
\test01\webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports = {
mode: 'development',
entry: {
// 'test': './src/test.js',
'template': './src/template.js'
},
output: {
// 这个路径是默认会被加入 devServer 的 contentBase 中
path: path.resolve(__dirname, 'dist'),
// filename: "[name].js"
filename: "./public/js/[name].js"
},
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
},
{
test: /\.css$/,
use: ["style-loader","css-loader"]
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: "My App",
// 模板文件存放的目录
template: "./html/template.html",
// 生成(打包)后的html存放目录
filename: "app.html",
minify: {
collapseWhitespace: true, // 折叠有助于文档树中文本节点的空白
removeComments: true, // 删除HTML注释
removeRedundantAttributes: true, // 当值匹配默认值时删除属性。
removeScriptTypeAttributes: true, // type="text/javascript"从script标签中删除。其他type属性值保持不变
removeStyleLinkTypeAttributes: true, // type="text/css"从style和link标签中删除。其他type属性值保持不变
useShortDoctype: true // doctype用短(HTML5)文档类型替换
},
}),
// new HtmlWebpackPlugin({
// // 模板文件存放的目录
// template: "./html/template1.html",
// // 生成(打包)后的html存放目录
// filename: "app1.html"
// }),
new CleanWebpackPlugin(),
],
};
npm install --save-dev css-loader
npm install --save-dev style-loader
npm start
运行\test01\dist\app.html
我们不希望通过js
的方式生成style
标签,希望把样式文件单独拿出来,放在dist目录下面的public
的css
目录里面,然后被引用。
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.26
Branch: branch01commit description:a0.26(Webpack03——example03-1-使用"style-loader","css-loader"只能是引入style属性,而不是引入css文件了)
tag:a0.26
我们需要安装mini-css-extract-plugin
插件
npm install --save-dev mini-css-extract-plugin
并且会用到MiniCssExtractPlugin.loader
,去掉style-loader
\test01\webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
mode: 'development',
entry: {
// 'test': './src/test.js',
'template': './src/template.js'
},
output: {
// 这个路径是默认会被加入 devServer 的 contentBase 中
path: path.resolve(__dirname, 'dist'),
// filename: "[name].js"
filename: "./public/js/[name].js"
},
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
},
{
test: /\.css$/,
// use: ["style-loader","css-loader"]
// 不希望通过js的方式生成style标签,因此不需要"style-loader",
use: [
{
loader: MiniCssExtractPlugin.loader
},
"css-loader"
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: "My App",
// 模板文件存放的目录
template: "./html/template.html",
// 生成(打包)后的html存放目录
filename: "app.html",
minify: {
collapseWhitespace: true, // 折叠有助于文档树中文本节点的空白
removeComments: true, // 删除HTML注释
removeRedundantAttributes: true, // 当值匹配默认值时删除属性。
removeScriptTypeAttributes: true, // type="text/javascript"从script标签中删除。其他type属性值保持不变
removeStyleLinkTypeAttributes: true, // type="text/css"从style和link标签中删除。其他type属性值保持不变
useShortDoctype: true // doctype用短(HTML5)文档类型替换
},
}),
// new HtmlWebpackPlugin({
// // 模板文件存放的目录
// template: "./html/template1.html",
// // 生成(打包)后的html存放目录
// filename: "app1.html"
// }),
new CleanWebpackPlugin(),
// 设置css提取路径
new MiniCssExtractPlugin({
filename: './public/css/[name].css'
})
],
};
npm start
\test01\dist\app.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Apptitle>
<link href="./public/css/template.css" rel="stylesheet">
head>
<body>
<script src="./public/js/template.js">script>
body>
html>
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.27
Branch: branch01commit description:a0.27(Webpack03——example03-2-使用mini-css-extract-plugin插件发布后引入css文件了)
tag:a0.27
更多细节参看文档:
注意:webpack更新地很快,别死记硬背,变化会非常地快,如果出现问题,一定要关注版本问题,同一个插件可能因为版本不同,导致不同的结果,兼容性有很大的问题。
涉及打包编译,一定会用到它,翻译过来就是源文件映射
,实际上我们新建的src目录就是源文件,而dist目录就是打包发布文件。
我们发布后的文件与开发的源文件是千差万别的,运行的时候万一报错,找这个错,是十分困难的。
我们实际运行在浏览器的代码是通过 webpack
打包合并甚至是压缩混淆过的代码,所生成的代码并不利于我们的调试和错误定位,我们可以通过 sourceMap
来解决这个问题,sourceMap
本质是一个记录了编译后代码与源代码的映射关系的文件,我们可以通过 webpack
的 devtool
选项来开启 sourceMap
module.exports = {
mode: 'production',
...
}
首先,编译后会为每一个编译文件生成一个对应的 .map
文件,同时在编译文件中添加一段对应的 map
文件引入代码
...
//# sourceMappingURL=xx.js.map
...
/*# sourceMappingURL=xx.css.map*/
同时,现代浏览器都能够识别 sourceMap
文件,如 chrome
,会在 Sources
面板中显示根据编译文件与对应的 map
文件定位到源文件中,有利于我们的调试和错误定位
\test01\src\fn.js
export default function() {
console.lo('fn........dsdsds');
}
\test01\src\template.js
import fn from './fn';
import './css/index.css';
console.log('template');
document.onclick = async function() {
fn();
};
\test01\webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
// mode: 'development',
mode: 'production',
entry: {
// 'test': './src/test.js',
'template': './src/template.js'
},
output: {
// 这个路径是默认会被加入 devServer 的 contentBase 中
path: path.resolve(__dirname, 'dist'),
// filename: "[name].js"
filename: "./public/js/[name].js"
},
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
},
{
test: /\.css$/,
// use: ["style-loader","css-loader"]
// 不希望通过js的方式生成style标签,因此不需要"style-loader",
use: [
{
loader: MiniCssExtractPlugin.loader
},
"css-loader"
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: "My App",
// 模板文件存放的目录
template: "./html/template.html",
// 生成(打包)后的html存放目录
filename: "app.html",
minify: {
collapseWhitespace: true, // 折叠有助于文档树中文本节点的空白
removeComments: true, // 删除HTML注释
removeRedundantAttributes: true, // 当值匹配默认值时删除属性。
removeScriptTypeAttributes: true, // type="text/javascript"从script标签中删除。其他type属性值保持不变
removeStyleLinkTypeAttributes: true, // type="text/css"从style和link标签中删除。其他type属性值保持不变
useShortDoctype: true // doctype用短(HTML5)文档类型替换
},
}),
// new HtmlWebpackPlugin({
// // 模板文件存放的目录
// template: "./html/template1.html",
// // 生成(打包)后的html存放目录
// filename: "app1.html"
// }),
new CleanWebpackPlugin(),
// 设置css提取路径
new MiniCssExtractPlugin({
filename: './public/css/[name].css'
})
],
};
npm start
很难定位到错误位置!!!并且时常报错也不是很准确!
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.28
Branch: branch01commit description:a0.28(Webpack03——example04-1-发布模式下打包后代码有问题,很难定位到源文件)
tag:a0.28
那如何根据这个报错,找到源文件出错位置呢?
这个时候就需要sourceMap
了。
\test01\webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
//mode: 'development',
mode: 'production',
devtool: 'source-map',
entry: {
// 'test': './src/test.js',
'template': './src/template.js'
},
output: {
// 这个路径是默认会被加入 devServer 的 contentBase 中
path: path.resolve(__dirname, 'dist'),
// filename: "[name].js"
filename: "./public/js/[name].js"
},
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
},
{
test: /\.css$/,
// use: ["style-loader","css-loader"]
// 不希望通过js的方式生成style标签,因此不需要"style-loader",
use: [
{
loader: MiniCssExtractPlugin.loader
},
"css-loader"
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: "My App",
// 模板文件存放的目录
template: "./html/template.html",
// 生成(打包)后的html存放目录
filename: "app.html",
minify: true
}),
// new HtmlWebpackPlugin({
// // 模板文件存放的目录
// template: "./html/template1.html",
// // 生成(打包)后的html存放目录
// filename: "app1.html"
// }),
new CleanWebpackPlugin(),
// 设置css提取路径
new MiniCssExtractPlugin({
filename: './public/css/[name].css'
})
],
};
npm start
\test01\dist\public\js\template.js.map
这里的映射信息可能看得不太懂,其实这个是给浏览器看的。
源文件路径及对应编译后的文件路径
“mappings”:记录源文件对应的信息(记录对应位置关系),就能知道源文件中的代码与编译后的文件代码的对应关系了。(它规定一种编码格式)
{
"version": 3,
"sources": [
"webpack:///public/js/template.js"
],
"names": [
"modules",
"installedModules",
"__webpack_require__",
"moduleId",
"exports",
"module",
"i",
"l",
"call",
"m",
"c",
"d",
"name",
"getter",
"o",
"Object",
"defineProperty",
"enumerable",
"get",
"r",
"Symbol",
"toStringTag",
"value",
"t",
"mode",
"__esModule",
"ns",
"create",
"key",
"bind",
"n",
"object",
"property",
"prototype",
"hasOwnProperty",
"p",
"s",
"__webpack_exports__",
"console",
"log",
"document",
"onclick",
"async",
"lo"
],
"mappings": "CAAS,SAAUA,GAET,IAAIC,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUC,QAGnC,IAAIC,EAASJ,EAAiBE,GAAY,CACzCG,EAAGH,EACHI,GAAG,EACHH,QAAS,IAUV,OANAJ,EAAQG,GAAUK,KAAKH,EAAOD,QAASC,EAAQA,EAAOD,QAASF,GAG/DG,EAAOE,GAAI,EAGJF,EAAOD,QAKfF,EAAoBO,EAAIT,EAGxBE,EAAoBQ,EAAIT,EAGxBC,EAAoBS,EAAI,SAASP,EAASQ,EAAMC,GAC3CX,EAAoBY,EAAEV,EAASQ,IAClCG,OAAOC,eAAeZ,EAASQ,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEX,EAAoBiB,EAAI,SAASf,GACX,oBAAXgB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAeZ,EAASgB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAeZ,EAAS,aAAc,CAAEkB,OAAO,KAQvDpB,EAAoBqB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQpB,EAAoBoB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,iBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFAzB,EAAoBiB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOpB,EAAoBS,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRxB,EAAoB4B,EAAI,SAASzB,GAChC,IAAIQ,EAASR,GAAUA,EAAOoB,WAC7B,WAAwB,OAAOpB,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAH,EAAoBS,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRX,EAAoBY,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG9B,EAAoBiC,EAAI,GAIjBjC,EAAoBA,EAAoBkC,EAAI,GAnFpD,CAsFC,CAEJ,SAAU/B,EAAQD,EAASF,KAM3B,SAAUG,EAAQgC,EAAqBnC,GAE7C,aAEAA,EAAoBiB,EAAEkB,GAQZnC,EAAoB,GAQ9BoC,QAAQC,IAAI,YAEZC,SAASC,QAAUC,iBAdfJ,QAAQK,GAAG",
"file": "./public/js/template.js",
"sourceRoot": ""
}
\webpackTest01\dist\index.js
最后一句代码://# sourceMappingURL=index.js.map
index.js.map 这个就是当前文件对应的映射文件
浏览器解析完sourcemap后,生成如下信息:
但是我们打开浏览器,去定位报404,没定位成功。
发现index.css指向没问题,但是template.js指向是有问题的,可能是配置问题,我们改一下output。
output: {
// 这个路径是默认会被加入 devServer 的 contentBase 中
path: path.resolve(__dirname, 'dist'),
filename: "[name].js"
// filename: "./public/js/[name].js"
},
还是不行,试着改成开发模式。
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
mode: 'development',
//mode: 'production',
devtool: 'source-map',
entry: {
// 'test': './src/test.js',
'template': './src/template.js'
},
output: {
// 这个路径是默认会被加入 devServer 的 contentBase 中
path: path.resolve(__dirname, 'dist'),
// filename: "[name].js"
filename: "./public/js/[name].js"
},
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
},
{
test: /\.css$/,
// use: ["style-loader","css-loader"]
// 不希望通过js的方式生成style标签,因此不需要"style-loader",
use: [
{
loader: MiniCssExtractPlugin.loader
},
"css-loader"
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: "My App",
// 模板文件存放的目录
template: "./html/template.html",
// 生成(打包)后的html存放目录
filename: "app.html",
minify: {
collapseWhitespace: true, // 折叠有助于文档树中文本节点的空白
removeComments: true, // 删除HTML注释
removeRedundantAttributes: true, // 当值匹配默认值时删除属性。
removeScriptTypeAttributes: true, // type="text/javascript"从script标签中删除。其他type属性值保持不变
removeStyleLinkTypeAttributes: true, // type="text/css"从style和link标签中删除。其他type属性值保持不变
useShortDoctype: true // doctype用短(HTML5)文档类型替换
},
}),
// new HtmlWebpackPlugin({
// // 模板文件存放的目录
// template: "./html/template1.html",
// // 生成(打包)后的html存放目录
// filename: "app1.html"
// }),
new CleanWebpackPlugin(),
// 设置css提取路径
new MiniCssExtractPlugin({
filename: './public/css/[name].css'
})
],
};
调成开发模式,是压缩后的代码,一压缩就失效,改成开发模式就好了。
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.29
Branch: branch01commit description:a0.29(Webpack03——example04-2-开发模式下打包后代码映射没有问题)
tag:a0.29
官网看手册!!!!
webpack4.0+
;webpack
配置devtool: "source-map"
生成的map
代码没有sourcesContent
,没有sourcesContent
的结果是你只能定位要压缩代码的位置,无法定位到源码的位置
minimize
如果mode是production类型,minimize的默认值是true,执行默认压缩,
sourceMap 正确配置如下:
const buildConfig = {
mode: "production",
output: {
path: distPath,
filename: "./js/[name].[hash].min.js",
publicPath: "./"
},
optimization: { // 1. 这个配置必须
minimize: false
},
plugins: [
].concat(baseConfig.htmlArray),
devtool: "source-map" // 2. 这个配置必须
}
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
// mode: 'development',
mode: 'production',
devtool: 'source-map',
entry: {
// 'test': './src/test.js',
'template': './src/template.js'
},
output: {
// 这个路径是默认会被加入 devServer 的 contentBase 中
path: path.resolve(__dirname, 'dist'),
// filename: "[name].js"
filename: "./public/js/[name].js"
},
optimization: { // 1. 这个配置必须
minimize: false
},
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
},
{
test: /\.css$/,
// use: ["style-loader","css-loader"]
// 不希望通过js的方式生成style标签,因此不需要"style-loader",
use: [
{
loader: MiniCssExtractPlugin.loader
},
"css-loader"
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: "My App",
// 模板文件存放的目录
template: "./html/template.html",
// 生成(打包)后的html存放目录
filename: "app.html",
minify: {
collapseWhitespace: true, // 折叠有助于文档树中文本节点的空白
removeComments: true, // 删除HTML注释
removeRedundantAttributes: true, // 当值匹配默认值时删除属性。
removeScriptTypeAttributes: true, // type="text/javascript"从script标签中删除。其他type属性值保持不变
removeStyleLinkTypeAttributes: true, // type="text/css"从style和link标签中删除。其他type属性值保持不变
useShortDoctype: true // doctype用短(HTML5)文档类型替换
},
}),
// new HtmlWebpackPlugin({
// // 模板文件存放的目录
// template: "./html/template1.html",
// // 生成(打包)后的html存放目录
// filename: "app1.html"
// }),
new CleanWebpackPlugin(),
// 设置css提取路径
new MiniCssExtractPlugin({
filename: './public/css/[name].css'
})
],
};
npm start
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.30
Branch: branch01commit description:a0.30(Webpack03——example04-3-生产模式下打包后代码解决映射出错的问题)
tag:a0.30
我们在官网能看到它有很多选项:
+++
非常快速, ++
快速, +
比较快, o
中等, -
比较慢, --
慢
devtool | 构建速 度 | 重新构建速 度 | 是否适用于生产环境 | 品质(quality) |
---|---|---|---|---|
(none) | + + + | + + + | yes | 打包后的代码 |
eval | + + + | + + + | no | 生成后的代码 |
cheap-eval-source-map | + | + + | no | 转换过的代码(仅限 行) |
cheap-module-eval-source-map | 0 | + + | no | 原始源代码(仅限 行) |
eval-source-map | – | + | no | 原始源代码 |
cheap-source-map | + | 0 | no | 转换过的代码(仅限 行) |
cheap-module-source-map | 0 | - | no | 原始源代码(仅限 行) |
inline-cheap-source-map | + | 0 | no | 转换过的代码(仅限 行) |
inline-cheap-module-source-map | 0 | - | no | 原始源代码(仅限 行) |
source-map | – | – | yes | 原始源代码 |
inline-source-map | – | – | no | 原始源代码 |
hidden-source-map | – | – | yes | 原始源代码 |
nosources-source-map | – | – | yes | 无源代码内容 |
这些选项通常用于生产环境中:
(none)
(省略 devtool
选项) - 不生成 source map。这是一个不错的选择。
source-map
- 整个 source map 作为一个单独的文件生成。它为 bundle 添加了一个引用注释,以便开发工具知道在哪里可以找到它。
你应该将你的服务器配置为,不允许普通用户访问 source map 文件!(上线推荐
hidden-source-map
)
hidden-source-map
- 与 source-map
相同,但不会为 bundle 添加引用注释。如果你只想 source map 映射那些源自错误报告的错误堆栈跟踪信息,但不想为浏览器开发工具暴露你的 source map,这个选项会很有用。
你不应将 source map 文件部署到 web 服务器。而是只将其用于错误报告工具。
nosources-source-map
- 创建的 source map 不包含 sourcesContent(源代码内容)
。它可以用来映射客户端上的堆栈跟踪,而无须暴露所有的源代码。你可以将 source map 文件部署到 web 服务器。
这仍然会暴露反编译后的文件名和结构,但它不会暴露原始代码。
在使用
uglifyjs-webpack-plugin
时,你必须提供sourceMap:true
选项来启用 source map 支持。
以下选项对于开发环境和生产环境并不理想。他们是一些特定场景下需要的,例如,针对一些第三方工具。
inline-source-map
- source map 转换为 DataUrl 后添加到 bundle 中。
cheap-source-map
- 没有列映射(column mapping)的 source map,忽略 loader source map。
inline-cheap-source-map
- 类似 cheap-source-map
,但是 source map 转换为 DataUrl 后添加到 bundle 中。
cheap-module-source-map
- 没有列映射(column mapping)的 source map,将 loader source map 简化为每行一个映射(mapping)。
inline-cheap-module-source-map
- 类似 cheap-module-source-map
,但是 source mapp 转换为 DataUrl 添加到 bundle 中。
// devtool: 'source-map',
devtool: 'inline-source-map',
生成的文件中就没有index.js.map文件了!
index.js.map文件的对应信息在其注释里,并转成了dataurl格式。
\webpackTest01\dist\index.js
!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=0)}([function(e,t,r){"use strict";r.r(t);console.lo("fn")}]);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vc3JjL2ZuLmpzIl0sIm5hbWVzIjpbImluc3RhbGxlZE1vZHVsZXMiLCJfX3dlYnBhY2tfcmVxdWlyZV9fIiwibW9kdWxlSWQiLCJleHBvcnRzIiwibW9kdWxlIiwiaSIsImwiLCJtb2R1bGVzIiwiY2FsbCIsIm0iLCJjIiwiZCIsIm5hbWUiLCJnZXR0ZXIiLCJvIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJlbnVtZXJhYmxlIiwiZ2V0IiwiciIsIlN5bWJvbCIsInRvU3RyaW5nVGFnIiwidmFsdWUiLCJ0IiwibW9kZSIsIl9fZXNNb2R1bGUiLCJucyIsImNyZWF0ZSIsImtleSIsImJpbmQiLCJuIiwib2JqZWN0IiwicHJvcGVydHkiLCJwcm90b3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsInAiLCJzIiwiY29uc29sZSIsImxvIl0sIm1hcHBpbmdzIjoiYUFDRSxJQUFJQSxFQUFtQixHQUd2QixTQUFTQyxFQUFvQkMsR0FHNUIsR0FBR0YsRUFBaUJFLEdBQ25CLE9BQU9GLEVBQWlCRSxHQUFVQyxRQUduQyxJQUFJQyxFQUFTSixFQUFpQkUsR0FBWSxDQUN6Q0csRUFBR0gsRUFDSEksR0FBRyxFQUNISCxRQUFTLElBVVYsT0FOQUksRUFBUUwsR0FBVU0sS0FBS0osRUFBT0QsUUFBU0MsRUFBUUEsRUFBT0QsUUFBU0YsR0FHL0RHLEVBQU9FLEdBQUksRUFHSkYsRUFBT0QsUUFLZkYsRUFBb0JRLEVBQUlGLEVBR3hCTixFQUFvQlMsRUFBSVYsRUFHeEJDLEVBQW9CVSxFQUFJLFNBQVNSLEVBQVNTLEVBQU1DLEdBQzNDWixFQUFvQmEsRUFBRVgsRUFBU1MsSUFDbENHLE9BQU9DLGVBQWViLEVBQVNTLEVBQU0sQ0FBRUssWUFBWSxFQUFNQyxJQUFLTCxLQUtoRVosRUFBb0JrQixFQUFJLFNBQVNoQixHQUNYLG9CQUFYaUIsUUFBMEJBLE9BQU9DLGFBQzFDTixPQUFPQyxlQUFlYixFQUFTaUIsT0FBT0MsWUFBYSxDQUFFQyxNQUFPLFdBRTdEUCxPQUFPQyxlQUFlYixFQUFTLGFBQWMsQ0FBRW1CLE9BQU8sS0FRdkRyQixFQUFvQnNCLEVBQUksU0FBU0QsRUFBT0UsR0FFdkMsR0FEVSxFQUFQQSxJQUFVRixFQUFRckIsRUFBb0JxQixJQUMvQixFQUFQRSxFQUFVLE9BQU9GLEVBQ3BCLEdBQVcsRUFBUEUsR0FBOEIsaUJBQVZGLEdBQXNCQSxHQUFTQSxFQUFNRyxXQUFZLE9BQU9ILEVBQ2hGLElBQUlJLEVBQUtYLE9BQU9ZLE9BQU8sTUFHdkIsR0FGQTFCLEVBQW9Ca0IsRUFBRU8sR0FDdEJYLE9BQU9DLGVBQWVVLEVBQUksVUFBVyxDQUFFVCxZQUFZLEVBQU1LLE1BQU9BLElBQ3RELEVBQVBFLEdBQTRCLGlCQUFURixFQUFtQixJQUFJLElBQUlNLEtBQU9OLEVBQU9yQixFQUFvQlUsRUFBRWUsRUFBSUUsRUFBSyxTQUFTQSxHQUFPLE9BQU9OLEVBQU1NLElBQVFDLEtBQUssS0FBTUQsSUFDOUksT0FBT0YsR0FJUnpCLEVBQW9CNkIsRUFBSSxTQUFTMUIsR0FDaEMsSUFBSVMsRUFBU1QsR0FBVUEsRUFBT3FCLFdBQzdCLFdBQXdCLE9BQU9yQixFQUFnQixTQUMvQyxXQUE4QixPQUFPQSxHQUV0QyxPQURBSCxFQUFvQlUsRUFBRUUsRUFBUSxJQUFLQSxHQUM1QkEsR0FJUlosRUFBb0JhLEVBQUksU0FBU2lCLEVBQVFDLEdBQVksT0FBT2pCLE9BQU9rQixVQUFVQyxlQUFlMUIsS0FBS3VCLEVBQVFDLElBR3pHL0IsRUFBb0JrQyxFQUFJLEdBSWpCbEMsRUFBb0JBLEVBQW9CbUMsRUFBSSxHLHNDQ2pGakRDLFFBQVFDLEdBQUciLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VzQ29udGVudCI6WyIgXHQvLyBUaGUgbW9kdWxlIGNhY2hlXG4gXHR2YXIgaW5zdGFsbGVkTW9kdWxlcyA9IHt9O1xuXG4gXHQvLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuIFx0ZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuXG4gXHRcdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuIFx0XHRpZihpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSkge1xuIFx0XHRcdHJldHVybiBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXS5leHBvcnRzO1xuIFx0XHR9XG4gXHRcdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG4gXHRcdHZhciBtb2R1bGUgPSBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSA9IHtcbiBcdFx0XHRpOiBtb2R1bGVJZCxcbiBcdFx0XHRsOiBmYWxzZSxcbiBcdFx0XHRleHBvcnRzOiB7fVxuIFx0XHR9O1xuXG4gXHRcdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuIFx0XHRtb2R1bGVzW21vZHVsZUlkXS5jYWxsKG1vZHVsZS5leHBvcnRzLCBtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcblxuIFx0XHQvLyBGbGFnIHRoZSBtb2R1bGUgYXMgbG9hZGVkXG4gXHRcdG1vZHVsZS5sID0gdHJ1ZTtcblxuIFx0XHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuIFx0XHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG4gXHR9XG5cblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGVzIG9iamVjdCAoX193ZWJwYWNrX21vZHVsZXNfXylcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubSA9IG1vZHVsZXM7XG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlIGNhY2hlXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmMgPSBpbnN0YWxsZWRNb2R1bGVzO1xuXG4gXHQvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9uIGZvciBoYXJtb255IGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uZCA9IGZ1bmN0aW9uKGV4cG9ydHMsIG5hbWUsIGdldHRlcikge1xuIFx0XHRpZighX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIG5hbWUpKSB7XG4gXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIG5hbWUsIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBnZXR0ZXIgfSk7XG4gXHRcdH1cbiBcdH07XG5cbiBcdC8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uciA9IGZ1bmN0aW9uKGV4cG9ydHMpIHtcbiBcdFx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG4gXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG4gXHRcdH1cbiBcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbiBcdH07XG5cbiBcdC8vIGNyZWF0ZSBhIGZha2UgbmFtZXNwYWNlIG9iamVjdFxuIFx0Ly8gbW9kZSAmIDE6IHZhbHVlIGlzIGEgbW9kdWxlIGlkLCByZXF1aXJlIGl0XG4gXHQvLyBtb2RlICYgMjogbWVyZ2UgYWxsIHByb3BlcnRpZXMgb2YgdmFsdWUgaW50byB0aGUgbnNcbiBcdC8vIG1vZGUgJiA0OiByZXR1cm4gdmFsdWUgd2hlbiBhbHJlYWR5IG5zIG9iamVjdFxuIFx0Ly8gbW9kZSAmIDh8MTogYmVoYXZlIGxpa2UgcmVxdWlyZVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy50ID0gZnVuY3Rpb24odmFsdWUsIG1vZGUpIHtcbiBcdFx0aWYobW9kZSAmIDEpIHZhbHVlID0gX193ZWJwYWNrX3JlcXVpcmVfXyh2YWx1ZSk7XG4gXHRcdGlmKG1vZGUgJiA4KSByZXR1cm4gdmFsdWU7XG4gXHRcdGlmKChtb2RlICYgNCkgJiYgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAmJiB2YWx1ZS5fX2VzTW9kdWxlKSByZXR1cm4gdmFsdWU7XG4gXHRcdHZhciBucyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gXHRcdF9fd2VicGFja19yZXF1aXJlX18ucihucyk7XG4gXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShucywgJ2RlZmF1bHQnLCB7IGVudW1lcmFibGU6IHRydWUsIHZhbHVlOiB2YWx1ZSB9KTtcbiBcdFx0aWYobW9kZSAmIDIgJiYgdHlwZW9mIHZhbHVlICE9ICdzdHJpbmcnKSBmb3IodmFyIGtleSBpbiB2YWx1ZSkgX193ZWJwYWNrX3JlcXVpcmVfXy5kKG5zLCBrZXksIGZ1bmN0aW9uKGtleSkgeyByZXR1cm4gdmFsdWVba2V5XTsgfS5iaW5kKG51bGwsIGtleSkpO1xuIFx0XHRyZXR1cm4gbnM7XG4gXHR9O1xuXG4gXHQvLyBnZXREZWZhdWx0RXhwb3J0IGZ1bmN0aW9uIGZvciBjb21wYXRpYmlsaXR5IHdpdGggbm9uLWhhcm1vbnkgbW9kdWxlc1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5uID0gZnVuY3Rpb24obW9kdWxlKSB7XG4gXHRcdHZhciBnZXR0ZXIgPSBtb2R1bGUgJiYgbW9kdWxlLl9fZXNNb2R1bGUgP1xuIFx0XHRcdGZ1bmN0aW9uIGdldERlZmF1bHQoKSB7IHJldHVybiBtb2R1bGVbJ2RlZmF1bHQnXTsgfSA6XG4gXHRcdFx0ZnVuY3Rpb24gZ2V0TW9kdWxlRXhwb3J0cygpIHsgcmV0dXJuIG1vZHVsZTsgfTtcbiBcdFx0X193ZWJwYWNrX3JlcXVpcmVfXy5kKGdldHRlciwgJ2EnLCBnZXR0ZXIpO1xuIFx0XHRyZXR1cm4gZ2V0dGVyO1xuIFx0fTtcblxuIFx0Ly8gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm8gPSBmdW5jdGlvbihvYmplY3QsIHByb3BlcnR5KSB7IHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBwcm9wZXJ0eSk7IH07XG5cbiBcdC8vIF9fd2VicGFja19wdWJsaWNfcGF0aF9fXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLnAgPSBcIlwiO1xuXG5cbiBcdC8vIExvYWQgZW50cnkgbW9kdWxlIGFuZCByZXR1cm4gZXhwb3J0c1xuIFx0cmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18oX193ZWJwYWNrX3JlcXVpcmVfXy5zID0gMCk7XG4iLCJleHBvcnQgZGVmYXVsdCBmdW5jdGlvbigpIHtcbiAgICBjb25zb2xlLmxvKCdmbicpO1xufSJdLCJzb3VyY2VSb290IjoiIn0=
注意webpack针对不同应用可能会产生各种各样的问题,去官网看文档。
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.31
Branch: branch01commit description:a0.31(Webpack03——example05-devtool: 'inline-source-map’的使用)
tag:a0.31
实际脚手架工具都有它,如React、Vue启动的时候,都会在本地给我们启动一个服务器。Webpack就给我们提供了这种本地开发的服务器。
每次的代码修改都需要重新编译打包,刷新浏览器,特别麻烦,我们可以通过安装 webpackDevServer
来改善这方面的体验
npm install --save-dev webpack-dev-server
启动命令:
npx webpack-dev-server
或者,package.json
中添加 scripts
...,
"scripts": {
"server": "webpack-dev-server"
}
npm install --save-dev webpack-dev-server
实际上装了WebpackDevServer
后,内部就自动会装一个开发服务器,它是node
写的,内部用到是一个express
框架,直接调用一个命令就可以把服务启动起来。
\test01\package.json
{
"name": "test01",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack",
"server": "webpack-dev-server"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"uglifyjs-webpack-plugin": "^2.2.0",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
},
"devDependencies": {
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.6.0",
"html-webpack-plugin": "^4.3.0",
"mini-css-extract-plugin": "^0.9.0",
"raw-loader": "^4.0.1",
"style-loader": "^1.2.1",
"webpack-dev-server": "^3.11.0"
}
}
npm run server
它帮助我们自动在本地启一个服务器,自动调用webpack.config
中的配置,进行webpack
打包,打包后的根目录就是output
中的path
。
同时我们发现一个问题,dist
目录下什么东西都没有,那么我们是怎么看到网页内容的呢?其实在这里需要注意的一件事情是开发服务器并不会帮助我们打包以后进行output
输出,即将打包后的内容输出到dist
目录下。而是在内存中开辟一个虚拟路径
,即打包后的文件和数据都是存放在内存
中的,我们是看不到的。
为什么这么去做呢?主要原因是这样做,程序编译、运行会更快,因为它会把打包编译生成的代码放在内存中(硬盘的操作必然比内存的操作慢很多),通过express
对对应的路径进行访问,实际我们访问url
时候,此时url
指向的是内存中的某一块,从而访问速度也非常地快。实际上在开发环境下,在启动vue
和react
时候,一样也看不到输出(原理同
),但可以显示在网页上,只有用build
命令打包生产,才可以看到目录中运行的文件。
综上它其实就是一个开发服务器,很多脚手架工具都是用它实现运行应用的。
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.32
Branch: branch01commit description:a0.32(Webpack03——example6-1-webpack-dev-server的使用)
tag:a0.32
修改 webpack.config.js
module.exports = {
...,
devServer: {
// 生成的虚拟目录路径(在内存中模拟生成的虚拟路径)
contentBase: "./dist",
// 自动开启浏览器
open: true,
// 端口
port: 8081
}
}
启动服务以后,webpack
不在会把打包后的文件生成到硬盘真实目录中了,而是直接存在了内存中(同时虚拟了一个存放目录路径),后期更新编译打包和访问速度大大提升!
( contentBase: "./dist"
)=> output path 是默认会被加入 devServer 的 contentBase 中,contentBase配与不配,它都会加进去的。
具体配置参见官方文档:
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
// mode: 'development',
mode: 'production',
// devtool: 'source-map',
devtool: 'inline-source-map',
entry: {
// 'test': './src/test.js',
'template': './src/template.js'
},
output: {
// 这个路径是默认会被加入 devServer 的 contentBase 中
path: path.resolve(__dirname, 'dist'),
// filename: "[name].js"
filename: "./public/js/[name].js"
},
optimization: { // 1. 这个配置必须
minimize: false
},
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
},
{
test: /\.css$/,
// use: ["style-loader","css-loader"]
// 不希望通过js的方式生成style标签,因此不需要"style-loader",
use: [
{
loader: MiniCssExtractPlugin.loader
},
"css-loader"
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: "My App",
// 模板文件存放的目录
template: "./html/template.html",
// 生成(打包)后的html存放目录
filename: "app.html",
minify: {
collapseWhitespace: true, // 折叠有助于文档树中文本节点的空白
removeComments: true, // 删除HTML注释
removeRedundantAttributes: true, // 当值匹配默认值时删除属性。
removeScriptTypeAttributes: true, // type="text/javascript"从script标签中删除。其他type属性值保持不变
removeStyleLinkTypeAttributes: true, // type="text/css"从style和link标签中删除。其他type属性值保持不变
useShortDoctype: true // doctype用短(HTML5)文档类型替换
},
}),
// new HtmlWebpackPlugin({
// // 模板文件存放的目录
// template: "./html/template1.html",
// // 生成(打包)后的html存放目录
// filename: "app1.html"
// }),
new CleanWebpackPlugin(),
// 设置css提取路径
new MiniCssExtractPlugin({
filename: './public/css/[name].css'
})
],
devServer: {
// 多目录,默认会(如果还想将其他目录映射到静态目录中可进行配置此参数)
contentBase: [path.join(__dirname, 'html')], // 项目目录下的html目录映射进去
open: true, // 自动打开浏览器
port: 8081,
index: 'app.html' // 默认首页
}
};
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.33
Branch: branch01commit description:a0.33(Webpack03——example6-1-webpack-dev-server的自定义contentBase)
tag:a0.33
当下前端的开发都是前后端分离开发的,前端开发过程中代码会运行在一个服务器环境下(如当前的 WebpackDevServer
),那么在处理一些后端请求的时候通常会出现跨域的问题。WebpackDevServer
内置了一个代理服务,通过内置代理就可以把我们的跨域请求转发目标服务器上(WebpackDevServer
内置的代理发送的请求属于后端 - node
,不受同源策略限制),具体如下:
const Koa = require('koa');
const KoaRouter = require('koa-router');
const app = new Koa();
const router = new KoaRouter();
router.get('/api/info', async ctx => {
ctx.body = {
username: 'zMouse',
gender: 'male'
}
})
app.use( router.routes() );
app.listen(8787);
axios({
url: 'http://localhost:8787/api/info'
}).then(res => {
console.log('res',res.data);
})
默认情况下,该代码运行以后会出现跨域请求错误,修改 webpack
配置
module.exports = {
...,
devServer: {
// 生成的虚拟目录路径
contentBase: "./dist",
// 自动开启浏览器
open: true,
// 端口
port: 8081,
proxy: {
'/api': {
target: 'http://localhost:8787'
}
}
}
}
通过 proxy
设置,当我们在当前 WebpackDevServer
环境下发送以 /api
开头的请求都会被转发到 http://localhost:8787 目标服务器下
axios({
//url: 'http://locahost:8081/api/info',
url: '/api/info'
}).then(res => {
console.log('res',res.data);
})
注意 url
地址要填写 WebpackDevServer
域,比如当前 WebpackDevServer
开启的是 http://localhost:8081,也就是我们当前前端代码运行的环境,那么请求的 url
也必须发送到这里,当我们的请求满足了 proxy
中设置的 /api
开头,那么就会把请求转发到 target
,所以最后的实际请求是:http://lcoahost:8787/api/info
注意:它仅做正向代理,就如同我们开发时用redux发请求时用的http-proxy-middleware
,反向代理时建议用Nginx
。
新建一个server01目录
npm init -y
npm i koa koa-router
\server01\app.js
const Koa = require('koa')
const KoaRouter = require('koa-router')
const app = new Koa();
const router = new KoaRouter();
router.get('/', async ctx => {
ctx.body = '大前端开发';
})
app.use(router.routes())
app.listen(7777);
启动:
node app
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.34
Branch: branch01commit description:a0.34(Webpack03——example07-1-配置nodejs的koa)
tag:a0.34
\server01\app.js
const Koa = require('koa')
const KoaRouter = require('koa-router')
const app = new Koa();
const router = new KoaRouter();
// router.get('/', async ctx => {
// ctx.body = '大前端开发';
// })
router.get('/api/data', async ctx => {
ctx.body = '大前端开发';
})
app.use(router.routes())
app.listen(7777);
\test01\src\template.js
import fn from './fn';
import './css/index.css';
console.log('template');
document.onclick = async function() {
let rs = await fetch("http://localhost:7777/api/data")
console.log('rs', rs);
// fn();
};
涉及跨域问题。
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.35
Branch: branch01commit description:a0.35(Webpack03——example07-2-前端请求后台,必然出跨域的问题)
tag:a0.35
\test01\webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
// mode: 'development',
mode: 'production',
devtool: 'source-map',
entry: {
// 'test': './src/test.js',
'template': './src/template.js'
},
output: {
// 这个路径是默认会被加入 devServer 的 contentBase 中
path: path.resolve(__dirname, 'dist'),
// filename: "[name].js"
filename: "./public/js/[name].js"
},
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
},
{
test: /\.css$/,
// use: ["style-loader","css-loader"]
// 不希望通过js的方式生成style标签,因此不需要"style-loader",
use: [
{
loader: MiniCssExtractPlugin.loader
},
"css-loader"
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: "My App",
// 模板文件存放的目录
template: "./html/template.html",
// 生成(打包)后的html存放目录
filename: "app.html",
minify: true
}),
// new HtmlWebpackPlugin({
// // 模板文件存放的目录
// template: "./html/template1.html",
// // 生成(打包)后的html存放目录
// filename: "app1.html"
// }),
new CleanWebpackPlugin(),
// 设置css提取路径
new MiniCssExtractPlugin({
filename: './public/css/[name].css'
})
],
devServer: {
//output path 是默认会被加入 devServer 的 contentBase 中,contentBase配与不配,它都会加进去的
// 多目录,默认会(如果还想将其他目录映射到静态目录中可进行配置此参数)
contentBase: [path.join(__dirname, 'html')], // 项目目录下的html目录映射进去
open: true, // 自动打开浏览器
port: 8081,
index: 'app.html', // 默认首页
proxy: {
// 服务器代理,当访问'/api'时,就代理到'http://localhost:7777'
'/api': {
target: 'http://localhost:7777'
}
}
}
};
\test01\src\template.js
import fn from './fn';
import './css/index.css';
console.log('template');
document.onclick = async function() {
// let rs = await fetch("http://localhost:7777/api/data")
let rs = await fetch('/api/data')
console.log('rs', rs);
// fn();
};
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.36
Branch: branch01commit description:a0.36(Webpack03——example07-3-前端请求后台,解决跨域的问题)
tag:a0.36
在开发过程中,我们希望代码变化后,页面可以跟着刷新,这个称为live reload,翻译过来是热重载。
我们在开发应用的时候,经常希望代码发生改变以后,能跟辅助重新刷新页面。webpack能重新编译,又能重新刷新页面。
它是通过WDS
做到的。
它是通过websocket进行通讯的!
其实webpack的内部运用到express框架(提供http服务),它来开服务器,我们通过浏览器访问该服务器,浏览器会跟express服务器建立一个链接,且是长链接websocket。当我们在后台修改代码以后,webpack会发现我们修改代码了,之后它会帮助进行编译,编译完成之后,它会通过express发送一个实时消息给当前的客户端浏览器(令其刷新页面),通过websocket办到的。
在之前当代码有变化,我们使用的 live reload
,也就是刷新整个页面,虽然这样为我们省掉了很多手动刷新页面的麻烦(丢失页面当中很多状态),但是这样即使只是修改了很小的内容,也会刷新整个页面,无法保持页面操作状态。HMR
随之就出现了,它的核心的局部(模块)更新,也就是不刷新页面,只更新变化的部分。
module.exports = {
...,
devServer: {
// 生成的虚拟目录路径
contentBase: "./dist",
// 自动开启浏览器
open: true,
// 端口
port: 8081,
// 开启热更新
hot:true,
// 即使 HMR 不生效,也不去刷新整个页面(选择开启)
hotOnly:true,
proxy: {
'/api': {
target: 'http://localhost:8787'
}
}
}
}
开启 HMR
以后,当代码发生变化,webpack
即会进行编译,并通过 websocket
通知客户端(浏览器),我们需要监听处理来自 webpack
的通知,然后通过 HMR
提供的 API
来完成我们的局部更新逻辑
export default function() {
console.log('start1!');
}
import fn1 from './fn1.js';
box1.onclick = fn1;
if (module.hot) {//如果开启 HMR
module.hot.accept('./fn1.js', function() {
// 更新逻辑
box1.onclick = fn1;
})
}
上面代码就是 当 ./fn1.js 模块代码发生变化的时候,把最新的 fn1 函数绑定到 box1.onclick 上
从上面就可以看到,HMR
其实就是以模块为单位,当模块代码发生修改的时候,通知客户端进行对应的更新,而客户端则根据具体的模块来更新我们的页面逻辑(这些逻辑需要自己去实现),好在当前一些常用的更新逻辑都有了现成的插件
样式热更新比较简单,style-loader
中就已经集成实现了,我们只需要在 use
中使用就可以了
react和vue脚手架工具已经把热更新集成进去了。
https://github.com/gaearon/react-hot-loader
react 脚手架中也有集成
\test01\src\template.js
import fn from './fn';
import './css/index.css';
console.log('template');
document.onclick = async function() {
// let rs = await fetch("http://localhost:7777/api/data")
let rs = await fetch('/api/data')
// console.log('rs', rs);
// console.log('我修改了代码!!!!!!!');
fn();
};
console.log(module.hot);
\test01\webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
// mode: 'development',
mode: 'production',
// devtool: 'source-map',
devtool: 'inline-source-map',
entry: {
// 'test': './src/test.js',
'template': './src/template.js'
},
output: {
// 这个路径是默认会被加入 devServer 的 contentBase 中
path: path.resolve(__dirname, 'dist'),
// filename: "[name].js"
filename: "./public/js/[name].js"
},
optimization: { // 1. 这个配置必须
minimize: false
},
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
},
{
test: /\.css$/,
// use: ["style-loader","css-loader"]
// 不希望通过js的方式生成style标签,因此不需要"style-loader",
use: [
{
loader: MiniCssExtractPlugin.loader
},
"css-loader"
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: "My App",
// 模板文件存放的目录
template: "./html/template.html",
// 生成(打包)后的html存放目录
filename: "app.html",
minify: {
collapseWhitespace: true, // 折叠有助于文档树中文本节点的空白
removeComments: true, // 删除HTML注释
removeRedundantAttributes: true, // 当值匹配默认值时删除属性。
removeScriptTypeAttributes: true, // type="text/javascript"从script标签中删除。其他type属性值保持不变
removeStyleLinkTypeAttributes: true, // type="text/css"从style和link标签中删除。其他type属性值保持不变
useShortDoctype: true // doctype用短(HTML5)文档类型替换
},
}),
// new HtmlWebpackPlugin({
// // 模板文件存放的目录
// template: "./html/template1.html",
// // 生成(打包)后的html存放目录
// filename: "app1.html"
// }),
new CleanWebpackPlugin(),
// 设置css提取路径
new MiniCssExtractPlugin({
filename: './public/css/[name].css'
})
],
devServer: {
// 多目录,默认会(如果还想将其他目录映射到静态目录中可进行配置此参数)
contentBase: [path.join(__dirname, 'html')], // 项目目录下的html目录映射进去
open: true, // 自动打开浏览器
port: 8081,
index: 'app.html', // 默认首页
proxy: {
// 服务器代理,当访问'/api'时,就代理到'http://localhost:7777'
'/api': {
target: 'http://localhost:7777'
}
},
// 开启热更新
hot:true,
// 即使 HMR 不生效,也不去刷新整个页面(选择开启)
hotOnly:true,
}
};
module.hot.accept
: 当我们的模块中有更新的时候,webpack
进行编译,同时将编译的模块以事件的形式通知给它。监听哪个模块的更新。
\test01\src\template.js
import fn from './fn';
import fn1 from './fn1';
import './css/index.css';
console.log('template');
document.onclick = async function() {
// let rs = await fetch("http://localhost:7777/api/data")
let rs = await fetch('/api/data')
// console.log('rs', rs);
// console.log('我修改了代码!!!!!!!');
fn();
};
let input = document.querySelector('input');
input.onfocus = function() {
fn1();
}
// console.log(module.hot);
if (module.hot) {
// module.hot.accept: 监听哪个模块的更新
module.hot.accept('./fn', () => {
console.log('fn更新了');
});
module.hot.accept('./fn1', () => {
console.log('fn1更新了....');
});
}
\test01\src\fn1.js
export default function() {
console.log('我是新的代码');
}
当我们代码更新,webpack
会进行监听,重新编译之后,会把更新的模块以事件的一种机制通过websocket
通知浏览器,浏览器通过当前的提供的module.hot.accept
来监听是哪个模块发生了更新,它不会刷新我们整个页面,以模块进行局部更新。
webpack的内容非常庞大,建议过过文档即可,之后使用到了再去看,不用死记硬背。
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.37
Branch: branch01commit description:a0.37(Webpack03——example08-1-模块热更新)
tag:a0.37
针对动态生成的页面:
\test01\src\meAlert.js
export default function meAlert() {
let button = document.createElement('button');
button.innerHTML = '按钮1';
document.body.appendChild(button);
return button;
}
\test01\src\template.js
import fn from './fn';
import fn1 from './fn1';
import meAlert from './meAlert';
import './css/index.css';
console.log('template');
document.onclick = async function() {
// let rs = await fetch("http://localhost:7777/api/data")
let rs = await fetch('/api/data')
// console.log('rs', rs);
// console.log('我修改了代码!!!!!!!');
fn();
};
let input = document.querySelector('input');
input.onfocus = function() {
fn1();
}
let btn = meAlert();
// console.log(module.hot);
if (module.hot) {
// module.hot.accept: 监听哪个模块的更新
module.hot.accept('./fn', () => {
console.log('fn更新了');
});
module.hot.accept('./fn1', () => {
console.log('fn1更新了....');
});
module.hot.accept('./kkbAlert', () => {
console.log('按钮更新了');
btn.remove();
btn = meAlert();
})
}
但是这种更新逻辑是按照原生写的,全这样写累死,框架有自己的更新逻辑。当我们的组件发生更新的时候,会调用框架中对应的渲染接口,而不是这样写,具体参考以上提供的vue或者react的热更新链接。
参考:https://github.com/6xiaoDi/blog-Webpack/tree/a0.38
Branch: branch01commit description:a0.38(Webpack03——example08-2-模块热更新-针对动态生成的页面)
tag:a0.38