一些常用的命令:
npm install --save-dev
//简写
npm i -D
npm i -D webpack
npm i -D webpack@
npm i -D webpack@beta
npm i -g webpack
有本地和全局两种安装方式,全局安装了,可以在任何地方公用一个Webpack可执行文件,而不用各个项目重复安装。但是推荐安装到本项目,原因:开发中,公司项目很多,老旧项目如果没有进行及时版本升级,新旧项目就很有可能目安装不同版本的Webpack而导致冲突。
下面进行简单的配置(目前一般都使用现成的脚手架)
按照顺序执行
1.初始化模块化开发的项目
npm init // 会生成一个package.json文件
npm -i -D webpack
package.json
{
"name": "demo_01",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack --mode development",
"build": "webpack --mode production"
},
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.40.2",
"webpack-cli": "^3.3.8"
}
}
项目目录:
|-- index.html
|-- main.js
|-- show.js
|-- webpack.config.js
|-- package.json
|-- node_modules
|-- main.css
index.html
Document
Webpack是一个打包模块化JavaScript的工具,它会从main.js出发,识别出源码中的模块化导入语句,递归地找出入口文件地所有依赖,将入口和其他所有依赖打包到一个单独地文件中。
main.js
const show = require('./show.js');
show('Wepack');
main.css
#app{ text-align: center; }
show.js
function show(content) {
window.document.getElementById("app").innerText = "Hello" + content;
}
module.exports = show;
webpack在执行构建时默认会从项目根目录下的webpack.config.js文件读取配置,所以还需要创建它
webpack.config.js
const path = require('path');
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname,'./dist')
}
}
entry: 必填, 配置模块的入口,可抽象成输入,Webpack执行构建的第一步将从入口开始,搜寻及递归解析出所有入口依赖的模块。
支持的类型: string、array、object(配置多个入口)
context:
在项目根目录执行以下命令
npm run dev
执行这个命令后,会发现项目多出一个dist目录,里边有一个bundle.js文件,buildle.js是一个可执行的JavaScript文件,包含页面依赖的两个模块main.js、show.js 以及内置的 webpackBootstrap 启动函数。
buildle.js部分代码:
/******/
(function(modules) { // webpackBootstrap
})
/***/ "./main.js":
/*!*****************!*\
!*** ./main.js ***!
\*****************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("// require('./main.css');\r\nconst show = __webpack_require__(/*! ./show.js */ \"./show.js\");\r\nshow('Wepack');\n\n//# sourceURL=webpack:///./main.js?");
/***/ }),
/***/ "./show.js":
/*!*****************!*\
!*** ./show.js ***!
\*****************/
/*! no static exports found */
/***/ (function(module, exports) {
eval("function show(content) { \r\n window.document.getElementById(\"app\").innerText = \"Hello\" + content; \r\n}\r\nmodule.exports = show;\n\n//# sourceURL=webpack:///./show.js?");
/***/ })
/******/ });
使用Loader
使用Loader的原因:webpack不支持解析CSS文件,要支持非JavaScript类型的文件,则需要使用Webpack的Loader机制。Loader可以看作具有文件转换功能的翻译员,配置里的module.rules数组配置了一组规则。目的是告诉Webpack在遇到哪些文件时使用哪些Loader去加载和转换。
执行命令:
npm i -D style-loader css-loader
接着使用main.css,修改以下几个文件
main.js
require('./main.css');
const show = require('./show.js');
show('Wepack');
webpack.config.js
const path = require('path');
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname,'./dist')
},
//热更新
watch: true,
watchOptions: {
ignored: /node_modules/
},
module:{
rules:[
{
test: /\.css$/,
use: ['style-loader','css-loader']
}
]
}
}
其中配置里的module.rules数组配置了一组规则,告诉Webpack在遇到哪些文件时使用哪些Loader去加载和转换.上面的配置告诉Webpack遇到.css结尾的文件时,先使用css-loader读取CSS文件,再由style-loader将CSS的内容注入JavaScript里。配置Loader的时候需要注意:
重新构建
npm run dev
发现bundle.js文件被更新了,里边注入了在main.css中写的CSS,而不是另外生成一个CSS文件。刷新网页的时候,发现样式被作用上了。 这样的操作就是把CSS写在了JavaScript里!这就是style-loader的功劳,工作原理:将CSS的内容用JavaScript里的字符串存储起来,在网页执行JavaScript时通过DOM操作,动态地向HTML head标签插入HTML style标签。
build.js
/***/ "./mian.css":
/*!******************!*\
!*** ./mian.css ***!
\******************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("var content = __webpack_require__(/*! !./node_modules/css-loader/dist/cjs.js!./mian.css */ \"./node_modules/css-loader/dist/cjs.js!./mian.css\");\n\nif (typeof content === 'string') {\n content = [[module.i, content, '']];\n}\n\nvar options = {}\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = __webpack_require__(/*! ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js */ \"./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n\n\n//# sourceURL=webpack:///./mian.css?");
/***/ }),
弊端:
从图中我们可以看到css被动态地插在head标签中的style标签里。
于是就会想着,如何让Webpack单独输出CSS文件,想要单独输出CSS文件,就要通过WebpackPlugin机制来实现。
使用Plugin
Plugin是用来扩展Webpack功能的,通过再构建流程里注入钩子实现,它为Webpack带来很大的灵活性。
以下实现将注入bundle.js文件里的CSS提取到单独的文件中
执行命令:
npm install --save-dev extract-text-webpack-plugin@next
网上很多说
extract-text-webpack-plugin不支持webpack4了,应该说是最新的稳定版不支持,上条命令安装的测试版的,还是可以使用的。我的webpack是4.40.2的.
官网这样配置
# for webpack 3
npm install --save-dev extract-text-webpack-plugin
# for webpack 2
npm install --save-dev [email protected]
# for webpack 1
npm install --save-dev [email protected]
推荐使用:
link
npm i --D mini-css-extract-plugin
每一次执行装载依赖的时候,我们可以通过去查看package.json里边的devDependencies就可以知道是否安装进去了。
{
"name": "demo_01",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack --mode development",
"build": "webpack --mode production"
},
"author": "",
"license": "ISC",
"devDependencies": {
"css-loader": "^3.2.0",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"html-webpack-plugin": "^4.0.0-beta.3",
"mini-css-extract-plugin": "^0.8.0",
"style-loader": "^1.0.0",
"webpack": "^4.40.2",
"webpack-cli": "^3.3.8"
}
}
更改配置
webpack.config.js
const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname,'./dist')
},
//热更新
watch: true,
watchOptions: {
ignored: /node_modules/
},
module:{
rules:[
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader']
})
},
]
},
plugins: [
new ExtractTextPlugin({filename:`[name].css`} ),
]
}
构建后会发现dist中生成了一个main.css文件.
这就是我们单独打包后输出的css文件
接着来试试mini-css-extract-plugin
执行命令
npm install --save-dev mini-css-extract-plugin
配置对比:
const path = require('path');
// const ExtractTextPlugin = require("extract-text-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname,'./dist')
},
plugins: [
// new ExtractTextPlugin({filename:`[name].css`} ),
new MiniCssExtractPlugin({
filename: `[name].css`,
chunkFilename: `[id].css`,
}),
],
//热更新
watch: true,
watchOptions: {
ignored: /node_modules/
},
module:{
// rules:[
// {
// test: /\.css$/,
// loader: ExtractTextPlugin.extract({
// fallback: 'style-loader',
// use: ['css-loader']
// })
// },
// ]
rules: [
{
test: /\.css$/,
use: [ [MiniCssExtractPlugin.loader, 'css-loader'],
'css-loader'
],
},
],
},
}
两者作用相同、用法基本一致
有一个问题,就是每一次我们更改生成的文件名的时候,重新构建,原来生成的文件那些不会自动被清理,因此我们可以使用clean-webpack-plugin插件来帮我们这些繁琐的工作
执行命令:
npm i -D clean-webpack-plugin
配置中添加:
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname,'./dist')
},
plugins: [
new CleanWebpackPlugin()//清理构建文件夹
]
}
到了这一步之后,dist就能够生成单独的.css文件了,我们把css文件单独抽出来了,这时候就需要解决怎么对应使用的问题了
webpack提供了一个插件
html-webpack-plugin:
执行命令:
npm i D html-webpack-plugin
进行配置
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname,'./dist')
},
plugins: [
new HtmlWebpackPlugin({
inject: 'body',
template: './index.html'
})
]
}
inject有四个值:true、body、head、false
还有更多的插件属性,可自行了解。
接着执行构建
npm run dev
在dist文件夹中,多出了一个文件 index.html
Document
从index.html的代码中可以看到: mini-css-extract-plugin插件从buildle.js中抽离了css,而html-webpack-plugin把css文件、js文件全部自动放进了.html文件中。形成了一个浏览器可阅读的文件。
上述调试过程十分麻烦,实际开发中我们可能需要:
执行命令:
npm i -D webpack-dev-server
然后在package.json里边的scripts对象添加:
"scripts": {
"start": "webpack-dev-server"
}
接着执行
npm run start
就会看到控制台输出:
Project is running at http://localhost:8080/
webpack output is served from /
这个过程中:
支持SourceMap
浏览器运行的JavaScript代码都是编译器输出的代码,这些代码可读性很差。我们如果需要进行断点调试的话,可以使用Source Map映射代码。
首先执行
npm run start --devtool source-map
接着关闭,重新执行
npm run start
就可以在浏览器中的Sources栏中看到可调式的源代码了。
如下图:
上述调试完整代码: link