为什么要用webpack
在webpack等打包工具出世之前,我们普通的H5项目是怎么处理错综复杂的脚本呢? 第一种方式:引用不同的脚本去使用不同的功能,但脚本太多的时候会导致网络瓶颈 第二种方式:使用一个大型js文件去引入所有代码,但这样会严重影响可读性,可维护性,作用域。
举个栗子: 由于浏览器不能直接解析less文件,我们可通过引入转换的插件(file watcher)把less实时转换为css并引入,但项目里面会多出一个map跟css文件,造成项目文件的臃肿。
用官方文档的说法:
node.js诞生可以让Javasrcipt在浏览器环境之外使用,而webpack运行在node.js中。CommonJS的require机制允许在文件中引用某个模块,如此一来就可以解决作用域的问题。
const HtmlWebpackPlugin = require('html-webpack-plugin')
webpack 关心性能和加载时间;它始终在改进或添加新功能,例如:异步地加载 chunk 和预取,以便为你的项目和用户提供最佳体验
核心概念
webpack有7个核心概念:
- 入口(entry)
- 输出(output)
- loader
- 插件(plugin)
- 模式(mode)
- 浏览器兼容性(brower compatibility)
- 环境(environment)
新建一个build文件夹,里面新建一个webpack.config.js
入口entry
这是打包的入口文件,所有的脚本将从这个入口文件开始
单入口
const path = require('path')
module.exports = {
entry: path.resolve(__dirname, '../src/main.js')
}
多入口
使用对象语法配置,更好扩展,例如一个项目有前台网页跟后台管理两个项目可用多入口管理。
entry: {
app: path.resolve(__dirname, '../src/main.js'),
admin: path.resolve(__dirname, '../src/admin.js'),
},
输出output
打包后输出的文件,[name]跟[hash:8]表示文件名跟入口的保持一致但后面加上了hash的后缀让每次生成的文件名是唯一的。
单入口
module.exports = {
output: {
filename: '[name].[hash:8].js',
path: path.resolve(__dirname, '../dist'),
},
}
多入口
module.exports = {
entry: {
app: './src/app.js',
admin: './src/admin.js',
},
output: {
filename: '\[name].js',
path: \_\_dirname + '/dist',
},
};
// 写入到硬盘:./dist/app.js, ./dist/admin.js
loader转化器
用于模块的源码的转换,也是同学们在配置webpack的时候频繁接触的一个配置项。
举个例子,加载typescript跟css文件需要用到ts-loader跟css-loader、style-loader, 如果没有对应的loader,打包会直接error掉。
我们可以这么配置:先 npm i css-loader style-loader
module: {
rules: [
{
test: /\.css\$/,
use: ['style-loader','css-loader']
},
{
test: /\.ts\$/,
use: 'ts-loader'
}
必须留意的是,loader的执行是从右到左,就是css-loader执行完,再交给style-loader执行,
plugin插件
这是webpack配置的核心,有一些loader无法实现的功能,就通过plugin去扩展,建立一个规范的插件系统,能让你每次搭建项目的时候省去很多成本。
举个例子,我们会使用HtmlWebpackPlugin这个插件去生成一个html,其中会引入入口文件main.js。 假设不用这个插件,会发生什么?
当然是不会生成这个html,因此HtmlWebpackPlugin插件也是webpack的必备配置之一
const HtmlWebpackPlugin = require('html-webpack-plugin')
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../public/index.html') // 同时引入main.js的hash名字
}),
],
模式mode
mode一共有production,development,node三种,如果没有设置,会默认为production
不同的mode对于默认优化的选项有所不同,环境变量也不同,具体需要了解每个插件的具体使用
选项 |
描述 |
development |
会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development |
production |
会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。为模块和 chunk 启用确定性的混淆名称,FlagDependencyUsag |