【Webpack的使用指南 02】Webpack的常用解决方案

时间:2022-12-26 15:06:56

前言

说是解决方案实际上更像是webpack的插件索引。

写这一篇的目的是为了形成一个索引,将来要用时直接来查找即可。

索引目录

  1. 自动构建HTML,可压缩空格,可给引用的js加版本号或随机数:html-webpack-plugin
  2. 处理CSS:css-loader与style-loader
  3. 处理LESS:less-loade与less
  4. 提取css代码到css文件中: extract-text-webpack-plugin
  5. 开发环境下的服务器搭建:webpack-dev-server
  6. 解析ES6代码:babel-core babel-preset-env babel-loader
  7. 解析ES6新增的对象函数:babel-polyfill
  8. 解析react的jsx语法:babel-preset-react
  9. 转换相对路径到绝度路径:nodejs的path模块
  10. 给文件加上hash值:[chunkhash],[hash]
  11. 清空输出文件夹之前的输出文件:clean-webpack-plugin
  12. 模块热替换:NamedModulesPlugin和HotModuleReplacementPlugin
  13. 环境变量
  14. 跨平台使用环境变量: cross-env
  15. 处理图片路径: file-loader和html-loader
  16. 图片压缩:image-webpack-loader
  17. 定位源文件代码:source-map
  18. 分离生产环境和开发环境的配置文件
  19. webpack输出文件体积与交互关系的可视化:webpack-bundle-analyzer

1.自动构建HTML,可压缩空格,可给引用的js加版本号或随机数:html-webpack-plugin

解决方案:使用插件 html-webpack-plugin

webpack.config.js如下:

module.exports = {
entry: './src/app.js',
output: {
path: __dirname + '/dist',
filename: 'app.bundle.js'
},
plugins: [new HtmlWebpackPlugin({
template: './src/模板文件.html',
filename: '构建的.html',
minify: {
collapseWhitespace: true,
},
hash: true,
})]
};

注意要有path,因为这个输出的html需要知道输出目录

2.处理CSS:css-loader与style-loader

loader用于对模块的源代码进行预处理转换。

解决方案:使用css-loaderstyle-loader

看一下项目结构:

【Webpack的使用指南 02】Webpack的常用解决方案

此时运行webpack命令会抛出错误:

【Webpack的使用指南 02】Webpack的常用解决方案

接下来安装 css-loader 和 style-loader

npm install --save-dev css-loader style-loader

再修改webpack.config.js为:

【Webpack的使用指南 02】Webpack的常用解决方案

这其中rules数组就是loader用来的匹配和转换资源的规则数组。

test代表匹配需转换文件的正则表达式,而图中表示匹配所有以css结尾的文件。

而use数组代表用哪些loader去处理这些匹配到的文件。

此时再运行webpack,打包后的文件bundle.js就包含了css代码。

其中css-loader负责加载css,打包css到js中。

而style-loader负责生成:在js运行时,将css代码通过style标签注入到dom中。

3.处理LESS:less-loade与less

解决方案:使用less-loader

但是用less-loader只是将LESS代码转换为css代码。如果要打包文件到js中,还是需要用到上面提到的css-loader和style-loader。

看一下项目结构:

【Webpack的使用指南 02】Webpack的常用解决方案

然后app.js的代码为:

import styles from './app.less';

console.info('我是一个js文件123')

为了解决这种情况,首先要安装 less-loader,而less-loader是基于less的,所以也要安装less。

npm i --save-dev less less-loader

修改webpack.config.js为:

module: {
rules: [
{
test: /\.less$/,
use: [ 'style-loader', 'css-loader', 'less-loader' ]
}
]
}

4.提取css代码到css文件中: extract-text-webpack-plugin

很多时候我们想要的效果并不是想要把几个LESS或者CSS处理好后,打包到一个js中,而是想要把它打包到一个css文件中。

此时就有了插件 extract-text-webpack-plugin

首先进行安装

npm i --save-dev extract-text-webpack-plugin

然后修改webpack.config.js为:

【Webpack的使用指南 02】Webpack的常用解决方案

与原配置对比可以发现,比html-webpack-plugin这个插件多做了一步,就是在匹配和转换规则里面的use中使用了ExtractTextPlugin.extract。

注意这里的fallback表示,在提取文件失败后,将继续使用style-loader去打包到js中。

此时运行webpack

可以发现输出目录build下生成了一个style.css文件,也就是我们在webpack.config.js中期望生成的文件,并且在生成的demo.html中被引用了。

5.开发环境下的服务器搭建:webpack-dev-server

webpack-dev-server可以在本地搭建一个简单的开发环境用的服务器,自动打开浏览器,而且还可以达到webpack -watch的效果。

首先安装一下:

npm i -g  webpack-dev-server
npm i --save-dev webpack-dev-server

这里不需要改动webpack.config.js,直接运行命令

webpack-dev-server

查看控制台输出:

【Webpack的使用指南 02】Webpack的常用解决方案

显示项目运行在http://localhost:8080/

webpack的输出目录的路径在/下面

并且这个服务器会自动识别输出目录下名为index的HTML文件,而我们之前输出的文件名为demo.html。

所以还需要将之前html-webpack-plugin中配置的filename改为index.html,或者直接用http://localhost:8080/demo.html也行。

当我们修改了源代码后,打开的网页还会自动更新。

为了更灵活的应用开发环境的服务器,也可以在webpack.config.js中加入如下代码:

【Webpack的使用指南 02】Webpack的常用解决方案

devServer配置 功能
port 修改端口为8787,而不是默认的8080。
open 为true表示会自动打开浏览器,而不是需要我们再手动打开浏览器并在里面输入http://localhost:8080。
compress 对本地server返回的文件提供gzip压缩
index 指定网站首页映射的文件,默认为index.html

6.解析ES6代码:babel-core babel-preset-env babel-loader

这里说是ES6,实际上可以认为是ECMAScript的高版本代码,只是代指而已。

babel的作用是将浏览器还未支持的这些高版本js代码转换成可以被指定浏览器支持的js代码。

这里列出可以转换的大致语法:

【Webpack的使用指南 02】Webpack的常用解决方案

那么首先就需要安装babel

npm install babel-core babel-preset-env --save-dev

然后,为了和webpack结合起来,要用到babel-loader

npm install babel-loader --save-dev

然后在webpack.config.js的rules数组中增加以下代码:

{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
}
}

这行代码的意思是用babel-loader解析除了node_modules文件下的所有js文件。

而babel-loader就是用babel去解析js代码。

options的内容类似于.babelrc文件的配置,有了这个就不需要.babelrc文件了。

presets表示预处理器,现在的babel不像以前需要很多预处理器了,只需要env这一个就够了。

修改之前的app.js中的代码为:

console.info('我是一个js文件123')
const doSomething=() => {
console.info('do do do')
}

使用webpack命令后,可以看到我们最后的打包js文件中代码变成了这样:

【Webpack的使用指南 02】Webpack的常用解决方案

7.解析ES6新增的对象函数:babel-polyfill

以下为这些新增函数:

【Webpack的使用指南 02】Webpack的常用解决方案

安装:

npm install --save-dev babel-polyfill

为了确保babel-polyfill被最先加载和解析,所以一般都是讲babel-polyfill在最开始的脚本中引入。

而在webpack中,就是在放到entry中,所以需要修改webpack.config.js中的配置为:

【Webpack的使用指南 02】Webpack的常用解决方案

8.解析react的jsx语法:babel-preset-react

安装

npm install --save-dev babel-preset-react

配置:

【Webpack的使用指南 02】Webpack的常用解决方案

这里是匹配所有以js或者jsx结尾的文件,并用 babel-preset-env和babel-preset-react进行解析

9.转换相对路径到绝度路径:nodejs的path模块

这里首先介绍一下nodejs的path模块的一个功能:resolve。

将相对路径转换为绝对路径。

在最开始引用path模块

var path = require('path');

然后可以在输出设置那里修改代码为:

  output: {
path: path.resolve(__dirname, 'build'),
filename: 'bundle.js'
},

和我们原来的代码没有任何区别。

10.给文件加上hash值:[chunkhash],[hash]

hash和chunkhash有区别,hash的话输出的文件用的都是同一个hash值,而chunkhash的话是根据模块来计算的,每个输出文件的hash值都不一样。

直接将输出文件改为

output: {
path: path.resolve(__dirname, 'build'),
filename: 'bundle.[chunkhash].js'
},

[chunkhash]就代表一串随机的hash值

11.清空输出文件夹之前的输出文件:clean-webpack-plugin

当我们像上面一样不断改变输出文件时,之前的输出文件并没有去掉。

为了解决这个问题就需要clean-webpack-plugin。

首先安装

npm i clean-webpack-plugin --save-dev

然后引用插件,并声明每次生成输出需要清空的文件夹

var CleanWebpackPlugin = require('clean-webpack-plugin');
var pathsToClean = [
'build',
]

再在插件配置中加入:

new CleanWebpackPlugin(pathsToClean)

12.模块热替换:NamedModulesPlugin和HotModuleReplacementPlugin

之前的webpack-dev-server提供了监听功能,只要代码改变,浏览器就会刷新。

但是模块热替换是不会刷新浏览器,只刷新修改到的那部分模块。

模块热替换无需安装。

首先需要引入模块

var webpack = require('webpack')

其实插件中加入:

new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin()

此时运行webpack可能会报错,我们需要把之前在输出环境中写的[chunkhash]改为[hash]

13.环境变量

可以在脚本中这么写:

"scripts": {

"dev": "webpack-dev-server",

"prod": "set NODE_ENV=production && webpack -p"

},

这样在webpack.config.js中这样修改上面的东西:

【Webpack的使用指南 02】Webpack的常用解决方案

if (isProduction) {
config.output.filename = 'bundle.[chunkhash].js'
} else {
config.plugins.push(new webpack.NamedModulesPlugin())
config.plugins.push(new webpack.HotModuleReplacementPlugin())
}

这样就可以根据环境的不同来运行不同的配置

14.跨平台使用环境变量: cross-env

上述设置环境变量的脚本中只有在window下才有效,在linux和mac上需要使用

"prod": "NODE_ENV=production webpack -p"

为了解决这个问题,使得不同平台的人能公用一套代码,我们可以使用cross-env。

首先进行安装:

npm i --save-dev cross-env

然后命令直接使用类似于mac上的用法即可

"prod": "cross-env NODE_ENV=production webpack -p"

15.处理图片路径: file-loader和html-loader

file-loader可以用来处理图片和字体文件在css文件中的路径问题,输出的css文件中会引用输出的文件地址。

html-loader可以用来处理html中,比如img元素的图片路径问题。

首先安装

npm i --save-dev file-loader html-loader

配置:

        {
test: /\.(gif|png|jpe?g|svg)$/i,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'src/images/'
}
}
},
{
test: /\.html$/,
use: [{
loader: 'html-loader',
options: {
minimize: true
}
}],
}

16.图片压缩:image-webpack-loader

安装:

npm i --save-dev image-webpack-loader

配置:

    {
test: /\.(gif|png|jpe?g|svg)$/i,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/'
}
},
{
loader: 'image-webpack-loader',
options: {
bypassOnDebug: true,
}
}
]
},

这里的options中也可以具体配置各个图片类型的压缩质量

17.定位源文件代码:source-map

如果我们用web-dev-server运行我们的输出文件,发现其中有些BUG,然后打开开发者工具取定位文件的时候,只会定位到我们的输出文件。

而这些输出文件是经过处理的,我们只有找到我们的源文件代码,然后进行相应的修改才能解决问题。

于是这里我们需要用到source-map。

很简单,在webpack.config.js中加入如下配置即可:

devtool: 'source-map',

就这么简单,还不需要安装什么插件。

但是这只对js有效,如果我们的css出现错误了呢,答案就是如下配置:

【Webpack的使用指南 02】Webpack的常用解决方案

18.分离生产环境和开发环境的配置文件

之前我们通过在命令中设置环境变量,并且通过环境变量来判断环境来进行不同的配置。

现在我们用官方推荐的方法来分离生产环境和开发环境的配置文件。

我们将webpack.config.js分为三个文件

  • webpack.common.js
  • webpack.dev.js
  • webpack.prod.js

其中webpack.common.config.js为生产环境和开发环境共有的配置,dev为开发环境独有的配置,prod为生成环境独有的配置。

而想要合成真正的配置文件,还需要一个工具:webpack-merge。

  npm install --save-dev webpack-merge

以下是我们之前的webpack.config.js代码:

var ExtractTextPlugin = require('extract-text-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var CleanWebpackPlugin = require('clean-webpack-plugin')
var path = require('path')
var webpack = require('webpack') var pathsToClean = [
'build',
] var isProduction = process.env.NODE_ENV === 'production' var config = {
entry: ['babel-polyfill', './src/app.js'],
output: {
path: path.resolve(__dirname, 'build'),
filename: '[name].[hash].js'
},
devtool: 'source-map',
devServer: {
port: 8787,
open: true,
compress: true,
index: 'demo.html'
},
plugins: [
new HtmlWebpackPlugin({
template: './template/index.html',
filename: 'demo.html',
minify: {
collapseWhitespace: true,
},
hash: true
}),
new ExtractTextPlugin({ filename: 'style.css', allChunks: false }),
new CleanWebpackPlugin(pathsToClean)
],
module: {
rules: [{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader?sourceMap']
})
},
{
test: /\.less$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader?sourceMap', 'less-loader?sourceMap']
})
},
{
test: /\.jsx?$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env', 'react']
}
}
},
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/'
}
},
{
loader: 'image-webpack-loader',
options: {
bypassOnDebug: true,
}
}
]
},
{
test: /\.html$/,
use: [{
loader: 'html-loader',
options: {
minimize: true
}
}],
}
]
}
}; if (isProduction) {
config.output.filename = '[name].[chunkhash].js'
} else {
config.plugins.push(new webpack.NamedModulesPlugin())
config.plugins.push(new webpack.HotModuleReplacementPlugin())
} module.exports = config

接下来分为三个文件,webpack.common.js:

var ExtractTextPlugin = require('extract-text-webpack-plugin')

var HtmlWebpackPlugin = require('html-webpack-plugin')

var CleanWebpackPlugin = require('clean-webpack-plugin')

var path = require('path')

var webpack = require('webpack')

var pathsToClean = [
'build',
] var isProduction = process.env.NODE_ENV === 'production' module.exports = {
entry: ['babel-polyfill', './src/app.js'],
output: {
path: path.resolve(__dirname, 'build'),
filename: '[name].[chunkhash].js'
},
plugins: [
new HtmlWebpackPlugin({
template: './template/index.html',
filename: 'demo.html',
minify: {
collapseWhitespace: true,
},
hash: isProduction
}),
new ExtractTextPlugin({ filename: '[name].[contenthash].css', allChunks: false }),
new CleanWebpackPlugin(pathsToClean)
],
module: {
rules: [{
test: /\.jsx?$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env', 'react']
}
}
},
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/'
}
},
{
loader: 'image-webpack-loader',
options: {
bypassOnDebug: true,
}
}
]
},
{
test: /\.html$/,
use: [{
loader: 'html-loader',
options: {
minimize: true
}
}],
}
]
}
};

然后是webpack.dev.js:

const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin') module.exports = merge(common, {
output: {
filename: '[name].[hash].js'
},
devtool: 'source-map',
devServer: {
port: 8787,
open: true,
compress: true,
index: 'demo.html'
},
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin()
],
module: {
rules: [{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader?sourceMap']
})
},
{
test: /\.less$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader?sourceMap', 'less-loader?sourceMap']
})
}
]
}
});

最后是webpack.prod.js:

const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const ExtractTextPlugin = require('extract-text-webpack-plugin') module.exports = merge(common, {
module: {
rules: [{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader']
})
},
{
test: /\.less$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'less-loader']
})
}
]
}
});

然后修改一下package.json中的脚本即可

  "scripts": {
"dev": "webpack-dev-server --config webpack.dev.js",
"prod": "cross-env NODE_ENV=production webpack -p --config webpack.prod.js"
},

19. webpack输出文件体积与交互关系的可视化:webpack-bundle-analyzer

安装:

npm install --save-dev webpack-bundle-analyzer

然后修改webpack.config.js:

const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

module.exports = merge(common, {
// ...
plugins: [
new BundleAnalyzerPlugin({ analyzerPort: 8919 })
],
});

这里的analyzerPort为打包后的本地展示网页的端口,默认是8888。

然后webpack即可。

效果图如下:

【Webpack的使用指南 02】Webpack的常用解决方案

总结

各个插件以及loader的玩法还有很多,这里不具体介绍。

【Webpack的使用指南 02】Webpack的常用解决方案的更多相关文章

  1. Webpack 傻瓜式指南(一)

    modules with dependencies   webpack   module bundler   static  assetss   .js .js .png Webpack傻瓜式指南 n ...

  2. 在找一份相对完整的Webpack项目配置指南么?这里有

    Webpack已经出来很久了,相关的文章也有很多,然而比较完整的例子却不是很多,让很多新手不知如何下脚,下脚了又遍地坑 说实话,官方文档是蛮乱的,而且有些还是错的错的..很多配置问题只有爬过坑才知道 ...

  3. 【Webpack的使用指南 01】Webpack入门

    使用Webpack有一段时间了,但是感觉之前学的用的都比较零散,所以在这里整理一下Webpack的使用知识,从入门到进阶. 创建项目 首先创建最简单的一个项目 npm init 得到以下项目结构: 安 ...

  4. Webpack傻瓜式指南(转)

    add by zhj: 作者写了三篇文章,这是第一篇幅,另外两篇参见 https://zhuanlan.zhihu.com/p/20397902 https://zhuanlan.zhihu.com/ ...

  5. Webpack的使用指南-Webpack小结

    参考文章: https://baijiahao.baidu.com/s?id=1594972657801970108&wfr=spider&for=pc 使用Webpack有一段时间了 ...

  6. webpack webpack-dev-server使用指南

    webpack-dev-server插件可以实现webpack的自动编译刷新 项目结构 pockage.js { "name": "webpack", &quo ...

  7. 玩转webpack(二):webpack的核心对象

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者介绍:陈柏信,腾讯前端开发,目前主要负责手Q游戏中心业务开发,以及项目相关的技术升级.架构优化等工作. 前言 webpack 是一个强大的模 ...

  8. Webpack 2 视频教程 012 - 理解Webpack 中的 CSS 作用域与 CSS Modules

    原文发表于我的技术博客 这是我免费发布的高质量超清「Webpack 2 视频教程」. Webpack 作为目前前端开发必备的框架,Webpack 发布了 2.0 版本,此视频就是基于 2.0 的版本讲 ...

  9. webpack入门(三)webpack的api

    终于到了webpack api这一篇,我都等不及了0.0; webpack is fed a configuration object. Depending on your usage of webp ...

随机推荐

  1. Qt中 QString 和int, char等的“相互”转换

    转载:http://blog.csdn.net/ei__nino/article/details/7297791 Qt中 int ,float ,double转换为QString 有两种方法 1.使用 ...

  2. CentOS 6.5系统安装配置LAMP(Apache+PHP5+MySQL)服务器环境

    安装篇: 一.安装Apache yum install httpd #根据提示,输入Y安装即可成功安装 /etc/init.d/httpd start#启动Apache 备注:Apache启动之后会提 ...

  3. poj 2481

    Cows Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 16163   Accepted: 5380 Description ...

  4. Codeforces Round #157 (Div. 2)

    A. Little Elephant and Chess 模拟. B. Little Elephant and Magic Square 枚举左上角,计算其余两个位置的值,在\(3\times 3\) ...

  5. 关于HTML标签(元素)的那些事?

    关于HTML标签(元素)的那些事? 在战场上,知己知彼,方能百战百胜:在商场上,知己知彼,亦能呼风唤雨:在情场上,知己知彼,才能幸福美满.当然啦,在我们前端开发上,亦要知己知彼,才能叱咤风云.关于HT ...

  6. Ant打jar包指定MainClass

    一般用ant打jar的时候不用指定程序的入口!这个jar一般是给其他app引用的. 但是如果该jar就是程序的启动jar.例如: java -jar abc.jar  这个时候需要指定jar的入口类! ...

  7. iOS开发常用国外网站清单

    工欲善其事必先利其器,最近发现临时查找一些东西容易浪费时间,花了点时间整理一下常用的网站,方便以后备用. 国内的code4app,ui4app,cocoachina,oschina,csdn就不说了, ...

  8. C/C++:C++友元类

    C++友元类: 正常情况下,一个类是訪问不到还有一个类的私有成员的. 就像以下这个: #include <iostream> class A{ private: int a; public ...

  9. swift 2 选择头像图片

    一句话选择单个头像图片 新建ImagePickerViewController类: /* let imagePicker = ImagePickerViewController() imagePick ...

  10. 细说Nullable&lt&semi;T&gt&semi;类型

    目录一.简介二.语法和用法三.类型的转换和运算四.装箱与拆箱五.GetType()方法六.ToString()方法七.System.Nullable帮助类八.语法糖 一.简介 众所周知,值类型变量不能 ...