webpack理解与脚手架搭建流程

您所在的位置:网站首页 骰子战争骰子介绍 webpack理解与脚手架搭建流程

webpack理解与脚手架搭建流程

#webpack理解与脚手架搭建流程| 来源: 网络整理| 查看: 265

一、概念

本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

二、核心概念

1、Entry(入口):指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。每个依赖项随即被处理,最后输出到称之为 bundles 的文件中。

在webpack配置文件中配置 entry 属性,来指定一个入口起点(或多个入口起点)。默认值为 ./src。

webpack.config.js

module.exports = { entry: './path/to/my/entry/file.js' };

2、Output(出口):告诉 webpack 在哪里输出它所创建的结果文件,以及如何命名这些文件,默认值为./dist。

webpack.config.js

const path = require('path'); module.exports = { entry: './path/to/my/entry/file.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'my-first-webpack.bundle.js' } };

在上面的示例中,我们通过 output.filename 和 output.path 属性,来告诉 webpack bundle 的名称,以及我们想要 bundle 生成(emit)到哪里。最上面导入的 path 模块是一个 Node.js 核心模块,用于操作文件路径。

3、Loader(模块转换器):将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。

在更高层面,在 webpack 的配置中 loader 有两个目标:

test 属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。use 属性,表示进行转换时,应该使用哪个 loader。

webpack.config.js

const path = require('path'); const config = { output: { filename: 'my-first-webpack.bundle.js' }, module: { rules: [ { test: /\.txt$/, use: 'raw-loader' } ] } }; module.exports = config;

以上配置中,对一个单独的 module 对象定义了 rules 属性,里面包含两个必须属性:test 和 use。这告诉 webpack 编译器(compiler) 如下信息:

嘿,webpack 编译器,当你碰到「在 require()/import 语句中被解析为 '.txt' 的路径」时,在你对它打包之前,先使用 raw-loader 转换一下。”*

4、Plugins(插件):在 Webpack 构建流程中的特定时机注入扩展逻辑来改变构建结果或做你想要的事情。

想要使用一个插件,你只需要 require() 它,然后把它添加到 plugins 数组中。多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建它的一个实例。

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装 const webpack = require('webpack'); // 用于访问内置插件 const config = { module: { rules: [ { test: /\.txt$/, use: 'raw-loader' } ] }, plugins: [ new HtmlWebpackPlugin({template: './src/index.html'}) ] }; module.exports = config;

5、Module(模块):开发者将程序分解成离散功能块,并称之为模块。

通过选择 development 或 production 之中的一个,来设置 mode 参数,你可以启用相应模式下的 webpack 内置的优化

module.exports = { mode: 'production' };

在webpack里一个模块对应着一个文件,webpack会从配置的 Entry 开始递归找出所有依赖的模块。

三、执行流程

webpack启动后会在entry里配置的module开始递归解析entry所依赖的所有module,每找到一个module, 就会根据配置的loader去找相应的转换规则,对module进行转换后在解析当前module所依赖的module,这些模块会以entry为分组,一个entry和所有相依赖的module也就是一个chunk,最后webpack会把所有chunk转换成文件输出,在整个流程中webpack会在恰当的时机执行plugin的逻辑

四、流程示例4.1 初始化:// 创建项目,先创建一个空文件夹 mkdir webpack_demo cd webpack_demo npm init // 输入这个命令后,终端会问你一系列诸如项目名称,项目描述,作者等信息,不过如果你不打算发布这个模块,直接一路回车就好。 //(也可以使用npm init -y这个命令来一次生成package.json文件,这样终端不会询问你问题)。 4.2 安装webpack:npm install webpack --global npm install webpack-cli --save-dev mkdir src // 创建src目录 cd src touch index.js touch hello.js cd .. mkdir dist // 创建dist目录 touch index.html

在hello.js中导出一个模块

// hello.js module.exports = function () { let hello = document.createElement('div'); hello.innerHTML = "hello world!"; return hello; };

在index.js中引入这个hello.js模块

// index.js const hello = require('./hello.js'); document.querySelector("#root").appendChild(hello());

在index.html下引入打包后的js文件bundle.js

Webpack demo 4.3 打包:// webpack全局安装的情况下,output后面的是打包后的文件路径,bundle.js为打包后的js文件名 webpack src/index.js --output dist/bundle.js /** --output可简写为-o 上述命令相当于把src文件夹下的index.js文件 打包到dist文件夹下的bundle.js, 这样就生成了打包后的文件供index.html引入**/

index.html文件在浏览器打开即可看到 hello world!

4.4 优化

通过配置文件来使用webpack

// 文件根目录下 touch webpack.config.js

写下如下简单配置代码:

// webpack.config.js const path = require('path'); module.exports = { entry: path.join(__dirname, "/src/index.js"), // 入口文件 output: { path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方 filename: "bundle.js" // 打包后输出文件的文件名 } } // path.join的功能是拼接路径片段 // __dirname是node.js中的一个全局变量,它指向当前执行脚本所在的目录

有了这个配置文件,我们只需在终端中运行webpack命令就可进行打包,这条命令会自动引用webpack.config.js文件中的配置选项

4.5 package.json文件中自定义脚本命令

Node项目一般都有一个package.json文件,该文件用于描述当前项目,其中有一个scripts属性,该属性可以自定义脚本命令,例如我们运行的打包命令,那么可以在scripts里添加自定义脚本为:

"scripts": { "build": "webpack" }, 五、构建本地服务5.1 webpack-dev-server配置本地服务器

Webpack提供了一个可选的本地开发服务器,这个本地服务器基于node.js构建,它是一个单独的组件,在webpack中进行配置之前需要单独安装它作为项目依赖:

npm install webpack-dev-server -D 5.2 devServer配置项contentBase:该配置项指定了服务器资源的根目录,如果不配置contentBase的话,那么contentBase默认是当前执行的目录,一般是项目的根目录port:指定了开启服务器的端口号,默认为8080host:配置 DevServer的服务器监听地址,默认为 127.0.0.1headers:该配置项可以在HTTP响应中注入一些HTTP响应头。例如:

headers: { 'X-foo': '112233' } historyApiFallback:该配置项属性是用来应对返回404页面时定向跳转到特定页面的。一般是应用在单页应用,比如在访问路由时候,访问不到该路由的时候,通过该配置项,设置属性值为true的时候,会自动跳转到 index.html下。当然我们也可以手动通过 正则来匹配路由// 跳到index.html页面 historyApiFallback: true // 使用正则来匹配路由 historyApiFallback: { rewrites: [ { from: /^\/user/, to: '/user.html' }, { from: /^\/home/, to: '/home.html' } ] } hot:该配置项是指模块替换换功能,DevServer 默认行为是在发现源代码被更新后通过自动刷新整个页面来做到实时预览的,但是开启模块热替换功能后,它是通过在不刷新整个页面的情况下通过使用新模块替换旧模块来做到实时预览的。proxy : 有时候我们使用webpack在本地启动服务器的时候,由于我们使用的访问的域名是 http://localhost:8081 这样的,但是我们服务端的接口是其他的,可以通过该配置来解决跨域的问题// 假设服务端接口域名为:百度新闻--海量中文资讯平台 proxy: { '/api': { target: '百度新闻--海量中文资讯平台', // 目标接口的域名 // secure: true, // https 的时候 使用该参数 changeOrigin: true, // 是否跨域 pathRewrite: { '^/api' : '' // 重写路径 } } }

inline:设置为true,当源文件改变时会自动刷新页面open:该属性用于DevServer启动且第一次构建完成时,自动使用我们的系统默认浏览器去打开网页。compress:配置是否启用 gzip 压缩,boolean 类型,默认为 falseoverlay:该属性是用来在编译出错的时候,在浏览器页面上显示错误。该属性值默认为false,需要的话,设置该参数为true5.3 添加配置项到webpack.config.js// webpack.config.js const path = require('path'); module.exports = { entry: path.join(__dirname, "/src/index.js"), // 入口文件 output: { path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方 filename: "bundle.js" // 打包后输出文件的文件名 }, devServer: { contentBase: path.join(__dirname, "dist"), hot: true, port: '8080', inline: true, open: true, overlay: true, proxy: { '/api': { target: '', changeOrigin: true, pathRewrite: { '^/api': '' } } } } } 5.4 在package.json文件中添加启动命令"scripts": { "build": "webpack", "dev": "webpack-dev-server --open" },

在终端输入npm run dev 即可运行服务器

5.5 Source Maps调试配置

在打包时生成对应于打包文件的.map文件,使得编译后的代码可读性更高,更易于调试。

// webpack.config.js const path = require('path'); module.exports = { entry: path.join(__dirname, "/src/index.js"), // 入口文件 output: { path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方 filename: "bundle.js" // 打包后输出文件的文件名 }, devServer: { contentBase: path.join(__dirname, "dist"), hot: true, port: '8080', inline: true, open: true, overlay: true, }, devtool: 'source-map' // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度 }

配置好后,再次运行npm run build 进行打包,在dist文件夹中会多出一个bundle.js.map。如代码有bug,在浏览器的调试工具中会提示错误出现的位置,这就是devtool:'source-map' 配置项的作用。

六、Loaders

loaders是webpack最强大的功能之一,通过不同的loader,webpack有能力调用外部的脚本或工具,实现对不同格式的文件的处理,例如把scss转为css,将ES66、ES7等语法转化为当前浏览器能识别的语法,将JSX转化为js等多项功能。Loaders需要单独安装并且需要在webpack.comfig.js中的modules配置项下进行配置,Loaders的配置包括以下几方面:

test:一个用以匹配loaders所处理文件的拓展名的正则表达式(必须)loader:loader的名称(必须)include/exclude: 手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选)options: 为loaders提供额外的设置选项(可选)6.1 配置css-loader

安装style-loader和css-loader

npm install style-loader css-loader -D

配置文件添加module

// webpack.config.js const path = require('path'); module.exports = { entry: path.join(__dirname, "/src/index.js"), // 入口文件 output: { path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方 filename: "bundle.js" // 打包后输出文件的文件名 }, devServer: { contentBase: path.join(__dirname, "dist"), hot: true, port: '8080', inline: true, open: true, overlay: true, }, devtool: 'source-map', // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度 module: { rules: [ { test: /\.css$/, // 正则匹配以.css结尾的文件 use: ['style-loader', 'css-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 } ] } }

在src文件夹下新建index.css文件,设置body的样式

/* index.css */ body { background: gray; }

在src文件夹下的index.js引入它

// index.js import './index.css' // 导入css const hello = require('./hello.js'); document.querySelector("#root").appendChild(hello());

运行npm run dev启动服务器,会发现页面背景颜色变成了灰色

6.2 配置sass

因为sass-loader依赖于node-sass,所以还要安装node-sass

npm install sass-loader node-sass -D

修改配置文件

// webpack.config.js const path = require('path'); module.exports = { entry: path.join(__dirname, "/src/index.js"), // 入口文件 output: { path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方 filename: "bundle.js" // 打包后输出文件的文件名 }, devServer: { contentBase: path.join(__dirname, "dist"), hot: true, port: '8080', inline: true, open: true, overlay: true, }, devtool: 'source-map', // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度 module: { rules: [ { test: /\.css$/, // 正则匹配以.css结尾的文件 use: ['style-loader', 'css-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 }, { test: /\.(scss|sass)$/, // 正则匹配以.scss和.sass结尾的文件 use: ['style-loader', 'css-loader', 'sass-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 } ] } } 七、Plugins(插件)

插件(Plugins)是用来拓展Webpack功能的,它们会在整个构建过程中生效,执行相关的任务。Loaders和Plugins常常被弄混,但是他们其实是完全不同的东西,可以这么来说,loaders是在打包构建过程中用来处理源文件的(JSX,Scss,Less..),一次处理一个,插件并不直接操作单个文件,它直接对整个构建过程其作用。

7.1 使用插件

通过npm进行安装,然后在webpack.config.js配置文件的plugins配置项中添加该插件的实例,以版权声明插件为例:

// webpack.config.js const path = require('path'); const webpack = require('webpack'); // 这个插件不需要安装,是基于webpack的,需要引入webpack模块 module.exports = { entry: path.join(__dirname, "/src/index.js"), // 入口文件 output: { path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方 filename: "bundle.js" // 打包后输出文件的文件名 }, devServer: { contentBase: path.join(__dirname, "dist"), hot: true, port: '8080', inline: true, open: true, overlay: true, }, devtool: 'source-map', // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度 module: { rules: [ { test: /\.css$/, // 正则匹配以.css结尾的文件 use: ['style-loader', 'css-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 }, { test: /\.(scss|sass)$/, // 正则匹配以.scss和.sass结尾的文件 use: ['style-loader', 'css-loader', 'sass-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 } ] }, plugins: [ new webpack.BannerPlugin('版权所有,翻版必究') // new一个插件的实例 ] }

运行npm run build 打包后,查看dist下面的handle.js:

cat dist/bundle.js /*! 版权所有,翻版必究 */function(){ /** u code **/ } 7.2 自动生成html文件(HtmlWebpackPlugin)

到目前为止我们都是使用一开始建好的index.html文件,而且也是手动引入bundle.js,要是以后我们引入不止一个js文件,而且更改js文件名的话,也得手动更改index.html中的js文件名,所以能不能自动生成index.html且自动引用打包后的js呢?HtmlWebpackPlugin插件就是用来解决这个问题的

我们对项目结构进行一些更改:

把整个dist文件夹删除在src文件夹下新建一个index.html(名称自定义)文件模板(当然这个是可选的,因为就算不设置模板,HtmlWebpackPlugin插件也会生成默认html文件,这里我们设置模块会让我们的开发更加灵活),如下: DOCTYPE html>

安装HtmlWebpackPlugin插件

npm install html-webpack-plugin -D

引入HtmlWebpackPlugin插件,并配置设置的模板:

// webpack.config.js const path = require('path'); const webpack = require('webpack'); // 这个插件不需要安装,是基于webpack的,需要引入webpack模块 const HtmlWebpackPlugin = require('html-webpack-plugin'); // 引入HtmlWebpackPlugin插件 module.exports = { entry: path.join(__dirname, "/src/index.js"), // 入口文件 output: { path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方 filename: "bundle.js" // 打包后输出文件的文件名 }, devServer: { contentBase: path.join(__dirname, "dist"), hot: true, port: '8080', inline: true, open: true, overlay: true, }, devtool: 'source-map', // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度 module: { rules: [ { test: /\.css$/, // 正则匹配以.css结尾的文件 use: ['style-loader', 'css-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 }, { test: /\.(scss|sass)$/, // 正则匹配以.scss和.sass结尾的文件 use: ['style-loader', 'css-loader', 'sass-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 } ] }, plugins: [ new webpack.BannerPlugin('版权所有,翻版必究'), // new一个插件的实例 new HtmlWebpackPlugin({ template: path.join(__dirname, "/src/index.html")// new一个这个插件的实例,并传入相关的参数 }) ] }

运行npm run build进行打包,dist文件夹自动生成,包含index.html、bundle.js、bundle.js.map三个文件

原理: 在output出口配置项中定义了出口文件所在的位置为dist文件夹,且出口文件名为bundle.js,所以HtmlWebpackPlugin会自动帮你在 dist/index.html 中引用名为bundle.js文件,如果在webpack.config.js文件中更改了出口文件名,dist/index.html 中也会自动更改该文件名

7.3 清理dist文件夹(CleanWebpackPlugin)

webpack会生成文件,然后将这些文件放置在dist文件夹中,但是webpack无法追踪到哪些文件是实际在项目中用到的。通常,在每次构建前清理dist文件夹,是比较推荐的做法,因此只会生成用到的文件,这时候就用到CleanWebpackPlugin插件了。

npm install clean-webpack-plugin -D // 同HtmlWebpackPlugin插件配置,webpack.config.js 添加两行代码 const {CleanWebpackPlugin} = require('clean-webpack-plugin'); // 引入CleanWebpackPlugin插件 new CleanWebpackPlugin(['dist']), // 所要清理的文件夹名称

现在我们每运行一次npm run build后就会发现,webpack会先将dist文件夹删除,然后再生产新的dist文件夹。

7.4 热更新(HotModuleReplacementPlugin)

HotModuleReplacementPlugin是一个很实用的插件,可以在我们修改代码后自动刷新预览效果。

设置方法:

devServer配置项中添加 hot:true 参数。因为HotModuleReplacementPlugin是webpack模块自带的,所以引入webpack后,在plugins配置项中直接使用即可。new webpack.HotModuleReplacementPlugin() // 热更新插件

npm run dev 启动项目后,我们尝试着修改hello.js的内容,会发现浏览器预览效果会自动刷新



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3