Webpack的一些基础认知

一些常用的命令:

  • 安装模块并保存到package.json的devDependencies
npm install --save-dev
//简写
npm i -D
  • 安装最新的稳定版
npm i -D webpack
  • 安装指定版本
npm i -D webpack@<version>
  • 安装最新的体验版本
npm i -D webpack@beta
  • 全局安装
npm i -g webpack

有本地和全局两种安装方式,全局安装了,可以在任何地方公用一个Webpack可执行文件,而不用各个项目重复安装。但是推荐安装到本项目,原因:开发中,公司项目很多,老旧项目如果没有进行及时版本升级,新旧项目就很有可能目安装不同版本的Webpack而导致冲突。

下面进行简单的配置(目前一般都使用现成的脚手架)

按照顺序执行

1.初始化模块化开发的项目

npm init // 会生成一个package.json文件
  1. 安装最新的稳定版本的webpack
npm -i -D webpack 
  1. 添加可执行命令,在package.json中script对象中添加两个属性dev、build

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

<!DOCTYPE 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>Document</title>
</head>
<body>
    <div id ="app" ></div>
</body>
<script src="./dist/bundle.js"></script>
</html>

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的时候需要注意:

  • use属性的值需要是一个由Loader名称组成的数组,Loader的执行顺序是由后到前的。
  • 每个Loader都可以通过URL querystring的方式传入参数。例如 css-loader? minimize 中的 minimize 告诉 css-loader 要开启 css 压缩

重新构建

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?");

/***/ }),

弊端:

  1. 导致JavaScript文件变长并且加载网页的时间变长。

image

从图中我们可以看到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 extract-text-webpack-plugin@2.1.2
# for webpack 1
npm install --save-dev extract-text-webpack-plugin@1.0.1

推荐使用:
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

  • true:默认值,script标签位于html文件的 body 底部
  • body:script标签位于html文件的 body 底部(同 true)
  • head:script 标签位于 head 标签内,如果操作dom的话就会在DOM节点没生成之前去挂载,就会报错
  • false:不插入生成的 js 文件,只是单纯的生成一个 html 文件

还有更多的插件属性,可自行了解。

接着执行构建

npm run dev

在dist文件夹中,多出了一个文件 index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
<link href="main.css" rel="stylesheet"></head>
<body>
    <div id="app">
    </div>
<script src="bundle.js"></script></body>
<script src="./dist/bundle.js"></script>
</html>

从index.html的代码中可以看到: mini-css-extract-plugin插件从buildle.js中抽离了css,而html-webpack-plugin把css文件、js文件全部自动放进了.html文件中。形成了一个浏览器可阅读的文件。

上述调试过程十分麻烦,实际开发中我们可能需要:

  • 提供HTTP服务而不是使用本地文件预览
  • 监听文件的变化并自动刷新网页,做到实时预览
  • 支持Source Map,以便调试。

执行命令:

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 /

如下图:
image

这个过程中:

  • DevServer会启动一个HTTP服务器用于服务网页请求,同时会帮助启动Webpack,并接收Webpack发出的文件更变信号,通过WebSocket协议自动刷新网页做到实时预览。访问这个地址的话,就能够访问dist目录下的index.html
  • Webpack在启动时可以开启监听模式,之后webpack会监听本地文件系统的变化,在发生变化时重新构建出新的结果。

支持SourceMap

浏览器运行的JavaScript代码都是编译器输出的代码,这些代码可读性很差。我们如果需要进行断点调试的话,可以使用Source Map映射代码。
首先执行

npm run start --devtool source-map 

接着关闭,重新执行

npm run start 

就可以在浏览器中的Sources栏中看到可调式的源代码了。
如下图:
在这里插入图片描述

上述调试完整代码: link

在这里插入图片描述
最后推荐一本书(自认为是一本好书,喷子想打我吗?):吴浩麟写的 深入浅出Webpack
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值