webpack
Posted 一天一个知识点
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了webpack相关的知识,希望对你有一定的参考价值。
package.json 有什么作用?
npm上发布包时,需要npm init生成package.json文件
package.json中的信息来描述这个包,并提供包所需要的依赖
webpack是什么?和其他同类型工具比有什么优势?
市面上已经存在的模块管理和打包工具并不适合大型的项目,尤其单页面 Web 应用程序。最紧迫的原因是如何在一个大规模的代码库中,维护各种模块资源的分割和存放,维护它们之间的依赖关系,并且无缝的将它们整合到一起生成适合浏览器端请求加载的静态资源。
这些已有的模块化工具并不能很好的完成如下的目标:
- 将依赖树拆分成按需加载的块
- 初始化加载的耗时尽量少
- 各种静态资源都可以视作模块
- 将第三方库整合成模块的能力
- 可以自定义打包逻辑的能力
- 适合大项目,无论是单页还是多页的 Web 应用
和其他同类型工具比有什么优势?
webpack的优势:
1.代码拆分
Webpack 有两种组织模块依赖的方式,同步和异步。异步依赖作为分割点,形成一个新的块。在优化了依赖树后,每一个异步区块都作为一个文件被打包。
2.Loader
Webpack 本身只能处理原生的 javascript 模块,但是 loader 转换器可以将各种类型的资源转换成 JavaScript 模块。这样,任何资源都可以成为 Webpack 可以处理的模块。
3.智能解析
Webpack 有一个智能解析器,几乎可以处理任何第三方库,无论它们的模块形式是 CommonJS、 AMD 还是普通的 JS 文件。甚至在加载依赖的时候,允许使用动态表达式 require("./templates/" + name + ".jade")。
4.插件系统
Webpack 还有一个功能丰富的插件系统。大多数内容功能都是基于这个插件系统运行的,还可以开发和使用开源的 Webpack 插件,来满足各式各样的需求。
5.快速运行
Webpack 使用异步 I/O 和多级缓存提高运行效率,这使得 Webpack 能够以令人难以置信的速度快速增量编译。
npm script是什么?如何使用?
npm 允许在package.json文件里面,使用scripts字段定义脚本命令。
"scripts": { "start": "node ./bin/www", "webpack": "webpack --config ./src/webpack.config.js", "watch": "onchange "src/**/*.js" "src/**/*.less" -- npm run webpack" }
输入npm run webpack或者npm run watch就可以执行对应的脚本
但是比如start 或 bulid 等,可以直接npm start
本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
1是一个供浏览器环境使用的模块打包工具。
2是一个预编译模块的方案。这个方案更加智能,因为它是在发布前预编译好的,不需要在浏览器中加载解释器。
3webpack将项目中用到的一切静态资源都视为模块,模块之间可以互相依赖,递归地构建一个依赖关系图。然后将所有这些模块打包一个bundle文件,由浏览器加载。 webpack对它们进行统一的管理及打包发布。
6 直接写AMD或ES 6的模块化代码,它都能编译成浏览器识别的JavaScript代码。甚至CommonJS规范的模块化,webpack也可以转换成浏览器使用的形式。webpack相当于加强版browserify,诞生伊始,瞄准的就是大型单页应用,而且其对React的支持是最好的。
webpack的两大特色:
1.code splitting(可以自动完成) 2.loader 可以处理各种类型的静态文件,并且支持串联操作
webpack 是以commonJS的形式来书写脚本滴,但对 AMD/CMD 的支持也很全面,方便旧项目进行代码迁移。
webpack具有requireJs和browserify的功能,但仍有很多自己的新特性:
1. 对 CommonJS 、 AMD 、ES6的语法做了兼容 2. 对js、css、图片等资源文件都支持打包 3. 串联式模块加载器以及插件机制,让其具有更好的灵活性和扩展性,例如提供对CoffeeScript、ES6的支持 4. 有独立的配置文件webpack.config.js 5. 可以将代码切割成不同的chunk,实现按需加载,降低了初始化时间 6. 支持 SourceUrls 和 SourceMaps,易于调试 7. 具有强大的Plugin接口,大多是内部插件,使用起来比较灵活 8.webpack 使用异步 IO 并具有多级缓存。这使得 webpack 很快且在增量编译上更加快
----------------------------------------------
package.json为配置文件,
webpack.common.js
它是高度可配置的,我们先理解四个核心概念:入口(entry)、输出(output)、loader、插件(plugins)
入口(entry)
入口(entry point)。入口起点告诉 webpack 从哪里开始, APP第一个启动文件。
简单规则:每个 html 页面都有一个入口起点。单页应用(SPA):一个入口起点,多页应用(MPA):多个入口起点。
简单语法
用法:entry: string | Arrary<string>
//webpack.config.js
module.exports = {
entry: ‘./src/index.js‘
};
entry属性的单个入口语法,在扩展配置的时候有失灵活性。它是下面的简写:
//webpack.config.js
module.exports = {
entry: {
main: ‘./src/index.js‘
}
};
对象语法,更常见的应该是多入口应用程序-多页应用(MPA)。
//webpack.config.js
module.export = {
entry: {
home: "./home.js",
about: "./about.js",
contact: "./contact.js"
}
};
此配置,告诉 webpack,我们 需要 3 个独立分离的依赖关系图.
在多页应用中,每当页面跳转时,服务器将为你获取一个新的 HTML 文档。页面重新加载新文档,并且资源被重新下载。
根据经验:每个 HTML 文档只使用一个入口起点。
输出(output)
如何处理归拢在一起的代码(bundled code)。output选项可以控制webpack如何向硬盘写入编译文件。注意,即使可以存在多个entry起点,但只指定一个output配置。
在 webpack 中配置output 属性的最低要求是,将它的值设置为一个对象,包括以下两点:
filename 用于输出文件的文件名。
目标输出目录 path 的绝对路径。
//webpack.config.js
module.exports = {
entry: ‘./src/index.js‘,
output: {
path: ‘./home/proj/public/assets‘,
filename: ‘bundle.js‘
}
};
此配置将一个单独的 bundle.js 文件输出到 ./home/proj/public/assets 目录中。
loader
webpack的目标是,让webpack聚焦于项目中的所有资源(asset), 而浏览器不需要关注考虑这些。 webpack把每个文件(.css, .html, .scss, .jpg, etc.)都作为模块处理。然而webpack自身只理解JavaScript。
webpack loader 在文件被添加到依赖图中时,将文件源代码转换为模块。
loader可以使你在import或"加载"模块时预处理文件。因此,loader类似于其他构建工具中“任务(task)”,并提供了处理前端构建步骤的强大方法。
在更高层面,在webpack的配置中loader有两个目标:
识别出应该被对应的loader进行转换的那些文件。(test属性)
转换这些文件,从而使其能够被添加到依赖图中(并且最终添加到bundle中)。(use属性)
//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‘
},
module: {
rules: [
{
test: /.txt$/,
use: ‘raw-loader‘
}
]
}
};
以上配置中,对一个单独的 module 对象定义了 rules 属性,里面包含两个必须属性:test 和use。这相当于告诉 webpack 编译器,当碰到「在 require()/import 语句中被解析为 .txt 的路径」时,在对它打包之前,先使用 raw-loader 转换一下。
在webpack配置中定义loader时,要定义在module.rules中,而不是rules。如果不这么做,webpack会给出严重警告
示例
例如,你可以使用loader告诉webpack加载css文件,或者将TypeScript转为JavaScript。为此,首先安装相对应的loader:
npm install -D css-loader
npm install -D ts-loader
然后指示webpack对每个.css使用css-loader, 以及对所有.ts文件使用ts-loader:
module.exports = {
module: {
rules: [
{ test: /.css$/, use: ‘css-loader‘ },
{ test: /.ts$/, use: ‘ts-loader‘ }
]
}
};
根据配置选项,下面的规范定义了同等的loader用法:
{test: /.css$/, use: ‘css-loader‘}
// 等同于
{test: /.css$/, use: [{
loader: ‘css-loader‘
}]}
// 等同于
{test: /.css$/, loader: ‘css-loader‘}
module.rules.loader 是 module.rules.use: [ { loader } ] 的简写。
在应用程序中,有三种使用loader的方式:
配置(推荐):在webpack.config.js文件中指定loader。
内联: 在每个imort语句中显示指定loader。
CLI: 在shell命令中指定它们。
配置
module.rules 允许你在 webpack 配置中指定多个 loader。 这是展示loader的一种简明方式,并且有助于使代码变得简洁。同时让你对各个loader 有个全局概览:
module: {
rules: [{
test: /.css$/,
use: [
‘style-loader‘,
{ loader: ‘scss-loader‘ },
{
loader: ‘css-loader‘,
options: {
modules: true
}
}
]
}]
}
内联
可以在import 语句或任何等效于 "import" 的方式中指定 loader。使用 ! 将资源中的 loader 分开。分开的每个部分都相对于当前目录解析。
import Styles from ‘style-loader!css-loader?modules!./styles.css‘
通过前置所有规则及使用!, 可以对应覆盖到配置中的任意loader。
选项可以传递查询参数,例如 ?key=value&foo=bar,或者一个 JSON 对象,例如 ?{"key":"value","foo":"bar"}。
尽可能使用 module.rules,因为这样可以减少源码中的代码量,并且可以在出错时,更快地调试和定位 loader 中的问题。
CLI
你也可以通过CLI使用loader:
webpack --module-bind jade-loader --module-bind ‘css=style-loader!css-loader‘
这会对.jade文件使用 jade-loader,对 .css文件使用 style-loader和 css-loader。
Loader特性
loader 支持链式传递。能够对资源使用流水线(pipeline)。一组链式的 loader 将按照先后顺序进行编译。loader 链中的第一个 loader 返回值给下一个 loader。在最后一个 loader,返回 webpack 所预期的 JavaScript。
loader 可以是同步的,也可以是异步的。
loader 运行在 Node.js 中,并且能够执行任何可能的操作。
loader 接收查询参数。用于对 loader 传递配置。
loader 也能够使用options 对象进行配置。
除了使用 package.json 常见的 main 属性,还可以将普通的 npm 模块导出为loader,做法是在 package.json 里定义一个 loader 字段。
插件(plugin)可以为 loader 带来更多特性。
loader 能够产生额外的任意文件。
loader 通过(loader)预处理函数,为 JavaScript 生态系统提供了更多能力。
解析Loader
loader 遵循标准的模块解析。多数情况下,loader 将从模块路径(通常将模块路径认为是npm install, node_modules)解析。
loader 模块需要导出为一个函数,并且使用 Node.js 兼容的 JavaScript 编写。通常使用 npm 来管理,也可以将自定义 loader 作为应用程序中的文件。按照约定,loader 通常被命名为 xxx-loader(例如 json-loader)。
插件-plugins
插件是 wepback 的支柱功能。webpack 自身也是构建于-你在 webpack 配置中用到的相同的插件系统之上!
插件目的在于解决 loader无法实现的其他事。
由于loader仅在每个文件的基础上执行转换,而插件(plugins) 常用于(但不限于)在打包模块的 “compilation” 和 “chunk” 生命周期执行操作和自定义功能。想要使用一个插件,你只需要 require() 它,然后把它添加到 plugins 数组中。
多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 来创建它的一个实例。
剖析
webpack 插件是一个具有 apply 属性的 JavaScript 对象。apply
属性会被 webpack compiler 调用,并且 compiler 对象可在整个编译生命周期访问。通过Function.prototype.apply方法,你可以把任意函数作为插件传递(this 将指向compiler)。我们可以在配置中使用这样的方式来内联自定义插件。
//ConsoleLogOnBuildWebpackPlugin.js
function ConsoleLogOnBuildWebpackPlugin() {
};
ConsoleLogOnBuildWebpackPlugin.prototype.apply = function(compiler) {
compiler.plugin(‘run‘, function(compiler, callback) {
console.log("webpack 构建过程开始!!!");
callback();
});
};
用法
由于插件可以携带参数/选项,你必须在webpack配置中,向plugins属性中传入new实例。
根据webpack的用法,可以有多种方式使用插件。但是,通过配置的方式使用是比较推荐的做法。
配置 (推荐)
//webpack.config.js
const HtmlWebpackPlugin = require(‘html-webpack-plugin‘); //installed via npm
const webpack = require(‘webpack‘); //to access built-in plugins
const path = require(‘path‘);
const config = {
entry: ‘./path/to/my/entry/file.js‘,
output: {
path: path.resolve(__dirname, ‘dist‘),
filename: ‘my-first-webpack.bundle.js‘
},
module: {
rules: [
{ test: /.txt$/, use: ‘raw-loader‘ }
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({template: ‘./src/index.html‘})
]0
};
module.exports = config;
Node API(不推荐)
即便使用 Node API,用户也应该在配置中传入 plugins 属性。compiler.apply并不是推荐的使用方式。
// some-node-script.js
const webpack = require(‘webpack‘); //访问 webpack 运行时(runtime)
const configuration = require(‘./webpack.config.js‘);
let compiler = webpack(configuration);
compiler.apply(new webpack.ProgressPlugin());
compiler.run(function(err, stats) {
// ...
});
总结
以上就是webpack中比较重要的四个概念,在平时开发过程中会经常遇到。里面还可以有很多的详细配置,需要我们在项目开发的过程中慢慢了解。
以上是关于webpack的主要内容,如果未能解决你的问题,请参考以下文章
webpackwebpack.base.conf.js基础配置
Webpackwebpack5 模块联邦(Module Federation)
Webpackwebpack5 模块联邦(Module Federation)实践
webpackwebpack的html-webpack-plugin中的title不起作用?(已解决)