前言
作为前端开发人员,webpack是我们用来打包发布的神兵利器,他的重要性不用我多说了,目前行业内大多数团队构建工具用的应该还是webpack,由此可见一斑。接下来我就说说我们如何利用webpack来构建我们应用。 以下内容基于webpack 4.16.0
webpack的基本使用
1.webpack 安装
npm install webpack webpack-cli --save-dev
2.webpack处理单页面
项目根目录下新建webpack.config.dev.js
const path=require('path');
module.exports={
entry:{
index:'./src/index.js'
},
output:{
filename:'[name].js',
path: path.resolve(__dirname, "dist"),
},
mode:"production" //开发模式下使用development
}
3.package配置
package.json中script里面添加:
"build": "webpack --config ./webpack.config.dev.js"
然后运行 npm run build 即可
4.webpack开发模式-热更新
npm install --save-dev webpack-dev-server
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
module.exports = {
entry: {
index:'./src/index.js'
},
output: {
filename:'[name].js',
path: path.resolve(__dirname, "dist"),
},
mode: "development", // 开发模式
devtool: "source-map", // 开启调试
devServer: {
contentBase: path.join(__dirname, "dist"),
port: 8000, // 本地服务器端口号
hot: true, // 热重载
overlay: true, // 如果代码出错,会在浏览器页面弹出“浮动层”。类似于 vue-cli 等脚手架
proxy: {
// 跨域代理转发
"/api": {
target: "https://m.weibo.cn",
changeOrigin: true,
logLevel: "debug",
headers: {
Cookie: ""
}
}
}
},
plugins: [
new HtmlWebpackPlugin({
filename: "index.html",
template: "./index.html"
}),
new webpack.NamedModulesPlugin(),//当开启 HMR 的时候使用该插件会显示模块的相对路径,建议用于开发环境。
new webpack.HotModuleReplacementPlugin()
]
};
pakage.json 配置
"dev": "webpack-dev-server --open --config webpack.config.dev.js"
运行npm run dev 即可
5.处理js
npm install babel-loader -D
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
}
]
}
6.处理css、less、sass
mini-css-extract-plugin 可以帮助我们将css导出到文件上,这样的好处是可以充分使用浏览器缓存。
npm install --save-dev mini-css-extract-plugin
npm install --save-dev css-loader
如果项目使用less,还需安装less-loader
npm install --save-dev less-loader
如果项目使用sass,还需安装sass-loader
npm install --save-dev sass-loader
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [
//输出css文件
new MiniCssExtractPlugin({
chunkFilename: 'assets/styles/[id]-[contenthash:8].css',
ignorOrder:true
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
],
},
{
test: /.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader'
]
},
{
test: /\.scss$/,
use: [{
loader:MiniCssExtractPlugin.loader,
}, {
loader: "css-loader"
}, {
loader: "sass-loader"
}
],
},
};
7.处理vue文件
npm install -D vue-loader vue-template-compiler
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
new VueLoaderPlugin()
]
}
8.处理图片
npm install -D file-loader url-loader
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
esModule: false, // 不加的话会有这种情况 img属性src="[object Module]"
limit: 1024 * 20,
name: 'assets/images/[name]-[contenthash:8].[ext]'
}
}
]
}
]
9.处理字体
rules: [
{
test: /\.(ttf|woff)$/,
use: [
{
loader: 'file-loader',
options: {
name:'assets/styles/font/[name]-[contenthash:8].[ext]'
}
},
{
loader: 'url-loader',
options: {
limit: 10240
}
}
]
}
]
10.处理svg
svg在前端中是使用频率非常高的图形资源,为了方便,我们可以通过标签式的方式来使用svg,无需编写什么image/backgroud 等。通过即可使用
npm install -D svg-sprite-loader svgo-loader
icons 下面的 index.js 写入以下内容:
//icons/index.js
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg组件
// register globally
Vue.component('svg-icon', SvgIcon)
//引入svg,这里最好是不同模块引入各自的文件夹,避免svg体量过大
const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('./svg', false, /\.svg$/)
requireAll(req)
入口 main.js 将 index.js 引入:
import '@/icons'
使用:
<svg-icon icon-class="eye"></svg-icon>
webpack 配置:
npm install svg-sprite-loader -D
npm install svgo svgo-loader --save-dev
{
test: /\.svg$/,
loader: [{
loader:'svg-sprite-loader',
option: {
symbolId:"icon-[name]"
}
},
{
loader:'svgo-loader',
options: {
plugins: [
{removeTitle: true},
{convertColors: {shorthex: false}},
{convertPathData: false}
]
}
},
]
}
11.cleanPlugin
默认会删除output指定的输出⽬目录
plugins:[
new CleanWebpackPlugin()
]
12.htmlwebpackplugin
BundleAnalyzerPlugin
npm install --save-dev webpack-bundle-analyzer
plugins: [
new BundleAnalyzerPlugin()
]
结语
总的来说,webpack能在我们做web优化方面提供许多遍历的帮助,这篇文章我们先简单介绍一个入门级的。接下来还会有个进阶篇。同时webpack也在不断地更新中,新版本会不断引入新的特性,使用也越来越简单。让我们拭目以待吧。
最终文件:
-
pakage.json
"scripts": { "dev": "webpack-dev-server --open --config webpack.config.dev.js", "build": "webpack --config webpack.config.prod.js" }, -
webpack.config.dev.js
const path=require('path'); const webpack = require("webpack"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const VueLoaderPlugin = require('vue-loader/lib/plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports={ entry:{ index:'./src/main.js' }, output:{ filename:'[name].js', path: path.resolve(__dirname, "dist"), }, mode:"development", //开发模式下使用development devServer: { contentBase: path.join(__dirname, "dist"), port: 8000, // 本地服务器端口号 hot: true, // 热重载 overlay: true, // 如果代码出错,会在浏览器页面弹出“浮动层”。类似于 vue-cli 等脚手架 proxy: { // 跨域代理转发 "/api": { target: "https://m.weibo.cn", changeOrigin: true, logLevel: "debug", headers: { Cookie: "" } } } }, module:{ rules:[ { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader', }, { test: /\.vue$/, loader: 'vue-loader' }, { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', ], }, { test: /.less$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'less-loader' ] }, { test: /\.scss$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader' ], }, { test: /\.(png|jpg|gif)$/, use: [ { loader: 'url-loader', options: { esModule: false, // 不加的话会有这种情况 img属性src="[object Module]" limit: 1024 * 20, name: 'assets/images/[name]-[contenthash:8].[ext]' } } ] }, { test: /\.(ttf|woff)$/, use: [ { loader: 'file-loader', options: { name:'./assets/styles/font/[name]-[contenthash:8].[ext]' } }, { loader: 'url-loader', options: { limit: 10240 } } ] } ] }, plugins: [ new HtmlWebpackPlugin({ filename: "index.html", template: "./src/template/index.html" }), new MiniCssExtractPlugin({ chunkFilename: 'assets/styles/[id]-[contenthash:8].css', ignorOrder:true }), new CleanWebpackPlugin(), new VueLoaderPlugin(), new webpack.NamedModulesPlugin(), new webpack.HotModuleReplacementPlugin() ] } -
webpack.config.prod.js
const path=require('path'); const webpack = require("webpack"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const VueLoaderPlugin = require('vue-loader/lib/plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports={ entry:{ index:'./src/main.js' }, output:{ filename:'[name].js', path: path.resolve(__dirname, "dist"), }, mode:"production", module:{ rules:[ { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader', }, { test: /\.vue$/, loader: 'vue-loader' }, { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', ], }, { test: /.less$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'less-loader' ] }, { test: /\.scss$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader' ], }, { test: /\.(png|jpg|gif)$/, use: [ { loader: 'url-loader', options: { esModule: false, // 不加的话会有这种情况 img属性src="[object Module]" limit: 1024 * 20, name: 'assets/images/[name]-[contenthash:8].[ext]' } } ] }, { test: /\.(ttf|woff)$/, use: [ { loader: 'file-loader', options: { name:'./assets/styles/font/[name]-[contenthash:8].[ext]' } }, { loader: 'url-loader', options: { limit: 10240 } } ] } ] }, plugins: [ new HtmlWebpackPlugin({ filename: "index.html", template: "./src/template/index.html" }), new MiniCssExtractPlugin({ chunkFilename: 'assets/styles/[id]-[contenthash:8].css', ignorOrder:true }), new CleanWebpackPlugin(), new VueLoaderPlugin(), new webpack.NamedModulesPlugin(), new webpack.HotModuleReplacementPlugin() ] }