【One by one系列】一步步学习Webpack打包
从其他领域过来瞻仰大前端时代的辉煌,一般都会特别疑惑,index.js``decfd4cb58ba3c6cc8c2.chunk.js
,e2a0f18f238432e4c037.css
,这些都是啥?这又是啥?Why?Why?这一切都是webpack干的好事。
webpack 是一个现代 JavaScript 应用程序的静态打包工具。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),去每一个文件中递归找依赖,其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
1.webpack到底是什么?
前端资源加载/打包工具
js→js→png→less→sass
- 静态分析模块的依赖关系
- 组织合并打包生成对应的静态资源
2.webpack4新特性
2.1 mode属性
-
development
- 浏览器调试工具
- 注释、开发阶段的详细错误日志和提示
- 快速和优化的增量构建机制
-
production
- 开启所有的优化代码
- 更小的bundle大小
- 去除掉只在开发阶段运行的代码
- Scope hoisting(作用域)和Tree-shaking(引入但是没有使用,抖掉)
webpack --mode development
2.2 开箱即用webassembly
2.3 支持多种模块类型
- javascript/auto
- javascript/esm
- javascript/dynamic
- json
- webassembly/experimental
2.4 0CJS-0配置
0配置,webpack4
受Parcel
打包工具启发,尽可能的让开发者运行项目的成本变低。webpack4
不再强制需要webpack.config.js
作为打包的入口配置文件,默认的入口为./src/
和默认的出口./dist
,小项目的福音。
2.5 新的插件系统
提供了针对插件和钩子的新API。
- 所有的hook由hooks对象统一管理,它将所有的hook作为可扩展的类属性。
- 当添加插件时,必须提供一个插件名称
- 开发插件时,可以选择
sync
/callback
/promise
作为插件类型 - 可以通过
this.hooks={myHook:new SyncHook(...)}
来注册hook了
2.6 node.js>=8.9.4
3.安装
3.1本地安装
cnpm install --save-dev webpack
npm install --save-dev webpack-cli
3.2全局安装(摒弃)
npm install --global webpack
- 不推荐全局安装 webpack。这会将你项目中的 webpack 锁定到指定版本,并且在使用不同的 webpack 版本的项目中,可能会导致构建失败。
4.Quick Start
4.1新建文件夹
mkdir webpack-demo
4.2新建文件
index.js
/**
* es6
* 写法
*
* */
import { hello } from './hello_module'
hello.sayHello()
/**
* node.js
* 写法
*/
// let hello=require('./hello_module')
// hello.sayHello();
hello_module.js
/**
* es6
*/
export default{
sayHello:function () {
console.log("hello")
}
}
/**
* nodejs
*/
module.exports = {
sayHello: function () {
console.log("hello")
}
}
4.3打包
.\node_modules\.bin\webpack --mode development index.js -o output_test_d.js
5kb
.\node_modules\.bin\webpack --mode production index.js -o output_test_p.js
2kb
5.配置文件
webpack.config.js
const path=require('path')
module.exports={
entry:'./input.js', //入口文件
output:{
path:path.resolve(__dirname,'dist'),
filename:'output.bundle.js'
}
}
const path=require('path')
module.exports={
entry:{
home:'./home.js'
about:'./about.js'
other:'./other.js'
}, //入口文件
output:{
path:path.resolve(__dirname,'dist'),
filename:'[name].bundle.js' //name->home or about or other
},
mode:"development"
}
$:webpack
6.Loaders
webpack预处理源文件,例如ts->js
- Files
- JSON
- Transpiling
- Templating
- Styling
- Linting&&Testing
- Frameworks
6.1 url-loader
当文件的大小小于某个指定size时,转成DataURL
,base64,不做雪碧图。
npm install url-loader --save-dev
import img from './image.png'
//webpack.config.js
module: {
rules: [{
test: /\.(png|jpg|gif)$/i,
use: [{
loader: 'url-loader',
options: {
limit: 8192
}
}]
}]
}//当文件是png,jpg,gif时,会使用url-loader来进行处理,文件小于8k时,会把文件以DataUrl的形式存储在文件中
6.2 babel-loader
负责把es6,es7的代码转化为es5的代码
- 安装
npm install -D babel-loader @babel/core @babel/preset-env webpack
moudule:{
rules:[
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
6.3 sass-loader
npm install sass-loader node-sass -D
npm install style-loader css-loader --save-dev
//webpack.config.js
module.exports={
..
module:{
rules:[{
test:/\.scss$/,
use:[
"style-loader",
"css-loader",
"sass-loader"
]
}]
}
}
7.Plugins插件
7.1 MinCssExtractPlugin.loader
css合并到一起
- 安装
npm install mini-css-extract-plugin -D
const path = require('path')
const MiniCssExtractPlugin=require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== 'production';
module.exports = {
entry: {
output: './src/index.js'
}, //入口文件
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js' //name->home or about or other
},
// mode: "production",
mode:"development",
plugins:[
new MiniCssExtractPlugin({
filename:"[name].[hash].css",//name->home
chunkFilename:"[id].[hash].css"
})
],
module: {
rules: [
{
test: /\.(png|jpg|gif)$/i,
use: [{
loader: 'url-loader',
options: {
limit: 8192
}
}]
}
,
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
,
{
test: /\.scss$/,
use: [
// "style-loader",
MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader"
]
}
]
}
}
7.2 DefinePlugin-减少代码冗余,定义全局变量
const path=require('path');
const MiniCssExtractPlugin=require("min-css-extract-plugin");
const webpack=require('webpack')
module.exports={
entry:{
home:'./home.js'
about:'./about.js'
other:'./other.js'
}, //入口文件
output:{
path:path.resolve(__dirname,'dist'),
filename:'[name].bundle.js' //name->home or about or other
},
mode:"development",
plugins:[
new MiniCssExtractPlugin({
filename:"[name].css",//name->home
chunkFilename:"[id].css"
}),
new webpack.DefinePlugin({ 'SERVICE_URL':JSON.stringify('http://www.sina.com')
})//就可以直接在js文件中使用SERVICE_URL中使用
],
module:{
rules:[{
test:/\.scss$/,
use:[
MinCssExtractPlugin.loader,
"css-loader",
"sass-loader"
]
}]
}
}
7.3 HtmlWebpackPlugin
-
目的:帮助我们去生产html文件,我们的js脚本不能独立运行(仅限前端,都知道有node,是可以的独立运行的),所以js必须包含在某个HTML文件中,才能运行。
-
安装
npm install --save-dev html-webpack-plugin
npm install html-webpack-plugin -D
const path = require('path')
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== 'production';
const webpack=require('webpack')
const HtmlWebpackPlugin=require('html-webpack-plugin')
module.exports = {
entry: {
output: './src/index.js'
}, //入口文件
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js' //name->home or about or other
},
// mode: "production",
mode: "development",
plugins: [
new MiniCssExtractPlugin({
filename: "[name].[hash].css",//name->home
chunkFilename: "[id].[hash].css"
}),
new webpack.DefinePlugin({
'SERVICE_URL': JSON.stringify('https://dev.example.com')
}),
// new HtmlWebpackPlugin()//base
new HtmlWebpackPlugin({
title:"Randy App",
filename:"index.html",
template:'template.html'
})
],
module: {
rules: [
{
test: /\.(png|jpg|gif)$/i,
use: [{
loader: 'url-loader',
options: {
limit: 8192
}
}]
}
,
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
,
{
test: /\.scss$/,
use: [
// "style-loader",
MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader"
]
}
]
}
}
8.热替换-自动刷新
npm install webpack-dev-server -D
const path = require('path')
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== 'production';
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: {
output: './src/index.js'
}, //入口文件
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js' //name->home or about or other
},
devServer: {
open:true,
contentBase: path.join(__dirname, "dist"),//output 路径
compress: true,//
port: 3000
// ,hot:false
//hot配置是否启用模块的热替换功能,
//devServer的默认行为是在发现源代码被变更后,
//通过自动刷新整个页面来做到事实预览,
//而开启hot后,
//将在不刷新整个页面的情况下通过新模块替换老模块来做到实时预览。
},
// mode: "production",
mode: "development",
plugins: [
new MiniCssExtractPlugin({
filename: "[name].[hash].css",//name->home
chunkFilename: "[id].[hash].css"
}),
new webpack.DefinePlugin({
'SERVICE_URL': JSON.stringify('https://dev.example.com')
}),
// new HtmlWebpackPlugin()//base
new HtmlWebpackPlugin({
title: "Randy App",
filename: "index.html",
template: 'template.html'
})
],
module: {
rules: [
{
test: /\.(png|jpg|gif)$/i,
use: [{
loader: 'url-loader',
options: {
limit: 8192
}
}]
}
,
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
,
{
test: /\.scss$/,
use: [
// "style-loader",
MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader"
]
}
]
}
}
{
"scripts": {
"start": "webpack-dev-server --hot",
"build":"webpack",
"dev":"webpack-dev-server"
},
"devDependencies": {
"@babel/core": "^7.8.4",
"@babel/preset-env": "^7.8.4",
"babel-loader": "^8.0.6",
"css-loader": "^3.4.2",
"fibers": "^4.0.2",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.9.0",
"node-sass": "^4.13.1",
"sass": "^1.25.0",
"sass-loader": "^8.0.2",
"style-loader": "^1.1.3",
"url-loader": "^3.0.0",
"webpack": "^4.41.6",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.10.3",
"file-loader": "^5.1.0",
"url-loader": "^3.0.0"
}
}
热启动:npm run start
- 原文作者:Garfield
- 原文链接:http://www.randyfield.cn/post/2020-02-20-webpack/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。