logo头像

求知若渴,虚心若愚

前端开发环境搭建(五)

webpack

Webpack 是一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。

安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 全局安装
npm install --global webpack

// 本地安装
// 要安装最新版本
npm install --save-dev webpack
// 安装特定版本
npm install --save-dev webpack@<version>

// 如果你使用 webpack 4+ 版本,你还需要安装 CLI
npm install --save-dev webpack-cli

// 安装体验版本
npm install webpack@beta
npm install webpack/webpack#<tagname/branchname>

// 安装这些最新体验版本时要小心!它们可能仍然包含 bug,因此不应该用于生产环境

TIP
安装webpack4版本后,必须安装webpack-cli

不推荐全局安装 webpack( npm install –global webpack)

这会将你项目中的 webpack 锁定到指定版本,并且在使用不同的 webpack 版本的项目中,可能会导致构建失败。

package.json

1
2
3
4
5
6
7
{
"scripts": {
"start": "npm run dev",
"dev": "webpack-dev-server --hot",
"build": "webpack --display-error-details --config webpack.prod.js"
}
}

tip
开发配置文件魔人名称,可以不用–config

webpack4之后需要 –mode 使用的时候注意

webpack 开发配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// webpack.config.js
const path = require('path')
const webpack = require('webpack')
const htmlWebpackPlugin = require('html-webpack-plugin')

// 导入配置文件
const { productConfig, productName } = require('./config')

module.exports = {
// 入口
// entry: path.join(__dirname, './src/main.js'),
entry: path.join(__dirname, productConfig[productName].entry),
// entry:['babel-polyfill',path.join(__dirname, productConfig[productName].entry)],

// 出口
output: {
// 输出文件目录
path: path.join(__dirname, productConfig[productName].output),
// 输出文件名称
filename: 'bundle.js'
},

// 有利于开发期间定位错误信息
devtool: 'eval-source-map',

// webpack-dev-server
devServer: {
// 自动打开浏览器
open: true,
// 端口号
port: 3000,
},

// 用来处理非JS的静态资源
module: {
rules: [
// 添加浏览器私有前缀postcss-loader
// 需要postcss.config.js配置文件,也需要postcss-loader和autoprefixer
{ test: /\.css$/, use: ["style-loader", "css-loader", "postcss-loader"] ,exclude: /node_modules|lib/ },
{ test: /\.(sass|scss)$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
{ test: /\.less$/,use:["style-loader!css-loader!less-loader"] },
{
test: /\.(png|jpg|jpeg|gif|svg)$/,
use: {
loader: 'url-loader',
options: {
// limit 就是阀值,值的单位:字节(byte)
limit: 8192
}
}
},
{
test: /\.(eot|svg|ttf|woff|woff2|otf)$/,
use: {
loader: 'url-loader',
options: {
// limit 就是阀值,值的单位:字节(byte)
limit: 8192
}
}
},

// 处理ES6或者更高级的JS语法:
{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules|lib/ },

// 处理 Vue单文件组件
{ test: /\.vue$/, use: 'vue-loader' },

// 让 html-loader 来处理HTML页面,此时,页面就会被webpack处理了
{ test: /\.html$/, use: 'html-loader' }
]
},

plugins: [
new htmlWebpackPlugin({
template: path.join(__dirname, productConfig[productName].html)
})
]
}

webpack 打包配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// webpack.prod.js
const path = require('path')
const webpack = require('webpack')
const htmlWebpackPlugin = require('html-webpack-plugin')

// 自动删除目录的包
const cleanWebpackPlugin = require('clean-webpack-plugin')
// 分离 css 到独立的文件中
const ExtractTextPlugin = require("extract-text-webpack-plugin")
// 压缩 css 资源文件
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
// 导入配置文件
const {productConfig,productName} = require('./config')

module.exports = {
// 入口
entry: {
// 我们写的js代码的入口
// app: path.join(__dirname, './src/main.js'),
app: path.join(__dirname, productConfig[productName].entry),
// 第三方js文件的入口
vendor: ['vue', 'vuex', 'vue-router', 'axios']
},

// 出口
output: {
// 输出文件目录
// path: path.join(__dirname, './dist'),
path: path.join(__dirname,productConfig[productName].output ),
// 修改出口js文件名称格式
// js 表示将生成的js文件放到js目录中
// [name] 表示入口entry中配置的文件名称
filename: 'js/[name].[chunkhash].js',
// 设置公共路径,用来解决CSS中引用字体路径的bug
publicPath: '/',
// 指定 代码分离 后的每个js文件的名称和文件路径
chunkFilename: 'js/[name].[chunkhash].js',
},

// postcss-loader 处理CSS浏览器私有前缀
// 用来处理非JS的静态资源
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use:["css-loader","postcss-loader"],
})
},
{
test: /\.(sass|scss)$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader', 'sass-loader']
})
},
{
test: /\.(png|jpg|jpeg|gif)$/,
use: {
loader: 'url-loader',
options: {
// limit 就是阀值,值的单位:字节(byte)
limit: 7168,

// images 表示将图片打包的images文件夹中
// [hash:10] 表示采用hash命名方式,并且名称长度为:10个字母
// [ext] 表示保留图片原始的后缀名称
name: 'images/[hash:10].[ext]'
}
}
},

{
test: /\.(eot|svg|ttf|woff|woff2|otf)$/,
use: {
loader: 'url-loader',
options: {
// limit 就是阀值,值的单位:字节(byte)
limit: 8192,
name: 'fonts/[hash:7].[ext]'
}
}
},

// 处理ES6或者更高级的JS语法:
{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules|lib/ },

// 处理 Vue单文件组件
{ test: /\.vue$/, use: 'vue-loader' },

// 让 html-loader 来处理HTML页面,此时,页面就会被webpack处理了
{ test: /\.html$/, use: 'html-loader' }
]
},

plugins: [
new htmlWebpackPlugin({
template: path.join(__dirname, productConfig[productName].html),

// 压缩HTML
minify: {
// 移除空白
collapseWhitespace: true,
// 移除注释
removeComments: true,
// 移除属性中的双引号
removeAttributeQuotes: true
}
}),

new cleanWebpackPlugin([productConfig[productName].output]),

// 抽离第三方包
new webpack.optimize.CommonsChunkPlugin({
// 将 entry 中指定的 ['vue', 'vue-router', 'axios'] 打包到名为 vendor 的js文件中
// 第三方包入口名称,对应 entry 中的 vendor 属性
name: 'vendor',
}),

// 压缩JS代码
new webpack.optimize.UglifyJsPlugin({
// 压缩
compress: {
// 移除警告
warnings: false
}
}),

// 指定环境为生产环境:vue会根据这一项启用压缩后的vue文件
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),

// 通过插件抽离 css (参数)
new ExtractTextPlugin('css/style.css'),
// 抽离css 的辅助压缩插件
new OptimizeCssAssetsPlugin(),
]
}

config 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 导出配置文件
module.exports = {
productName:'demo',//指定当前的项目名称
// 当前的项目配置:
// entry: 入口
// output:出口
// html: html文件位置
productConfig:{
demo:{
entry:'./src/demo/main.js',
output:'./dist/demo',
html:'./src/demo/index.html',
},
}
}
  • 通过配置config.js文件,可以运行开发多个项目,互不干扰
支付宝打赏 微信打赏

赞赏是对我们的肯定!