webpack的基本能力:处理依赖、模块化、打包
webpack的工作原理
简单的说就是分析代码,找到“require”、“exports”、“define”等关键词,并替换成对应模块的引用。在一个配置文件中,指明对某些文件进行编译、压缩、组合等任务。把你的项目当成一个整体,通过一个给定的主文件(index.js),webpack将从这个文件开始找到你的项目的所有的依赖文件,使用loaders处理他们,最后打包为一个浏览器可以识别的js文件。
在没有使用webpack之前:
举个例子:index.html里面有一大堆的css和js文件,如a.js b.js c.js等等
(1)a.js要用到b.js里面的饿一个函数,则a.js要放在b.js后面
(2)c.js要用到a.js里面的一个函数,则c.js要放在a.js后面
(3)b.js又要用到某个js文件里面的函数,则b.js就要放在其后面
如果有N多个js文件,需要手动处理他们的关系,即容易出错。
使用webpack:
webpack的理念就是一切皆模块化,把一堆的css文件和js文件放在一个总的入口文件,通过require引入,剩下的事情webpack会处理,包括所有模块的前后依赖关系,打包、压缩、合并成一个js文件,公共代码抽离成一个js文件、某些自己指定的js单独打包,模块可以是css/js/imsge/font等等。
webpack 4.29.6 webpack-cli 3.2.0 node v10.15.1
初始化项目
新建一个目录,初始化 package.json 回车回车回车
npm init
然后安装webpack和一些主要插件
cnpm i webpack webpack-cli webpack-dev-server webpack-merge html-webpack-plugin clean-webpack-plugin progress-bar-webpack-plugin copy-webpack-plugin --save-dev
–save 保存到配置目录里面
-dev 只在开发环境中使用 生成环境不用
-g 保存到全局
然后新建src
目录 里面创建index.js(入口文件) 和 index.html (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>webapcktitle>
head>
<body>
body>
html>
//index.js
console.log('初始化')
新建一个目录build
里面创建文件webpack.common.js
webpack.dev.js
webpack.prod.js
//webpack.common.js
const path = require('path');
const webpack = require('webpack'); // 这个插件不需要安装,是基于webpack的,需要引入webpack模块
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 引入HtmlWebpackPlugin插件
const CleanWebpackPlugin = require('clean-webpack-plugin'); // 引入CleanWebpackPlugin插件
const CopyWebpackPlugin = require('copy-webpack-plugin'); //拷贝文件
const ProgressBarPlugin = require('progress-bar-webpack-plugin'); //打包过程
module.exports = {
entry: path.resolve(__dirname,'../src/index.js'), // 入口文件
output: {
path: path.join(__dirname, "../dist"), //打包后的文件存放的地方
filename: "js/[name].js" //打包后输出文件的文件名
},
devtool: 'inline-source-map', // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度
module: {
rules: [{
test: /\.(png|jpe?g|gif|svg|webp)$/i,
use: [{
loader: 'url-loader',
options: {
limit: 10240,
fallback: 'file-loader'
}
}]
}]
},
plugins: [
new webpack.BannerPlugin('版权所有,翻版必究'), // new一个插件的实例
new HtmlWebpackPlugin({
template: path.join(__dirname, "../src/index.html") // new一个这个插件的实例,并传入相关的参数
}),
new webpack.HotModuleReplacementPlugin(), // 热更新插件
new CopyWebpackPlugin([{ //拷贝文件
from: path.join(__dirname, '../src/assets'),
to: path.join(__dirname, `../dist/assets`)
}]),
new ProgressBarPlugin({
callback:function(e,k){
//打包过程
}
})
]
}
// webpack.dev.js
const merge = require('webpack-merge'); // 引入webpack-merge功能模块
const common = require('./webpack.common.js'); // 引入webpack.common.js
const ip = require('ip').address();
module.exports = merge(common, { // 将webpack.common.js合并到当前文件
devServer: {
contentBase: "./dist", // 本地服务器所加载文件的目录
port: 8088, // 设置端口号为8088
host: ip || "localhost",
inline: true, // 文件修改后实时刷新
historyApiFallback: true, //不跳转
hot: true, //热加载
quiet: true
}
})
// webpack.prod.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const { CleanWebpackPlugin } = require("clean-webpack-plugin");// 引入CleanWebpackPlugin插件
module.exports = merge(common, { // 将webpack.common.js合并到当前文件
// devtool: 'source-map', // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度
plugins: [
new CleanWebpackPlugin(), // 所要清理的文件夹名称
]
})
最后需要修改下package.json文件
开发模式用dev文件 打包用的时候用prod文件
"scripts": {
"build": "webpack --config build/webpack.prod.js",
"serve": "webpack-dev-server --open --config build/webpack.dev.js"
},
然后先启动本地,看下游览器是否启动,控制台是否打印出信息,能启动则表示初始化配置成功
npm run serve
然后测试打包
npm run build
可以发现打包生成的js文件已经被自动引入html文件中
只需要配置入口和出口2个地方
入口
//webpack.common.js
entry:{
main: path.resolve(__dirname,'../src/index.js'),
header:path.resolve(__dirname,'../src/header.js')
},
出口 需要配置几个出口就几个出口
//webpack.common.js
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, "../src/index.html"),
filename:'index.html',
chunks:['main'] // 与入口文件对应的模块名
}),
new HtmlWebpackPlugin({
template:path.join(__dirname,'../src/index.html'),
filename:'header.html',
chunks:['header'] // 与入口文件对应的模块名
}),
安装和配置
cnpm install css-loader sass-loader node-sass postcss-loader autoprefixer mini-css-extract-plugin --save-dev
修改webpack配置
//webpack.common.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
/* 代码省略*/
module: {
rules: [
{
test:/\.css$/,
use:[MiniCssExtractPlugin.loader,'css-loader'] // 从右向左解析原则
},
{
test:/\.scss$/,
use:[
MiniCssExtractPlugin.loader,'css-loader',{
loader:'postcss-loader',
options:{
plugins:[require('autoprefixer')]
}
},'sass-loader'] // 从右向左解析原则
},{
test: /\.(png|jpe?g|gif|svg|webp)$/i,
use: [{
loader: 'url-loader',
options: {
limit: 10240,
fallback: 'file-loader'
}
}]
}
]
},
/* 代码省略*/
plugins: [
new MiniCssExtractPlugin({
filename:'css/[name].css',
chunkFilename: '[id].css'
})
]
根目录创建postcss.config.js
所有css3前面加前缀 兼容写法
module.exports = {
plugins: [require('autoprefixer')] // 引用该插件即可了
}
我们的入口文件是js,所以我们在入口js中引入我们的css和sass文件
import './css.css'
import './css.scss'
启动和打包都可以看到效果
引入babel
cnpm install babel-loader @babel/core @babel/preset-env @babel/polyfill --save-dev
转换es6到es5
// webpack.common.js
module.exports = {
// 省略其它配置 ...
module:{
rules:[
{
test:/\.js$/,
use:{
loader:'babel-loader',
options:{
presets:['@babel/preset-env']
}
},
exclude:/node_modules/
},
]
}
}
最新的api编译成es5
方法1
在配置中修改
module.exports = {
entry: {
main: ["@babel/polyfill",path.resolve(__dirname, '../src/index.js')],
header: path.resolve(__dirname, '../src/header.js')
},
方法2
在入口地方引入@babel/polyfill
import "@babel/polyfill"
总结
这些就是整个webpack的初始化搭建,平时开发一些简单的项目是完全够用的,如果需要做复杂的项目还需要考虑兼容vue、react等框架,还有一些webpack的优化,这个就需要后续继续学习和了解的地方