因项目需要,用webpack搭建一个常用功能的环境。
初步功能罗列如下:
自动配置多入口出口
less转css
css前缀自动补齐
css提取成单独文件
css压缩
图片压缩
引入字体和svg js Babel 压缩
css和js的分离/合并和过滤
1.建立并且进入文件夹
mkdir webpack4.29.6 && cd webpack4.29.6
复制代码
2.如下图建立各个demo文件和图片
index.html:
<!DOCTYPE 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>test</title>
</head>
<body>
随便写一些index2333
</body>
</html>
复制代码
<!DOCTYPE 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>test</title>
</head>
<body>
随便写一些about2333
</body>
</html>
复制代码
其他的文件可以先空着,图片先不导入也没关系。
3建立package.json(以下所有命令都是在webpack4.29.6文件夹下运行)
npm init -y
复制代码
4.安装以下几个依赖
(webpack/webpack-cli这两个需要注意,3.x以前版本是合并在一起的,4.x后拆分了
webpack-dev-server:起服务
html-webpack-plugin:动态生成html
webpack-merge:合并webpack配置文件)
npm install -D webpack webpack-cli webpack-dev-server html-webpack-plugin webpack-merge
复制代码
确保局部依赖和全局依赖版本都如下图是最新的(看清楚了,webpack是4.29.6的,如果你因为网络问题装成3.几的,后面将全部报错。这步很关键,不然你会有无穷尽的麻烦,如果实在不成功可以先把全局node下的webpack相关文件删除,window在c盘/Program Files/nodejs/下)。
5.建立三个webpack配置文本(1.common2.dev3.prod)并且分别写入
touch webpack.common.js webpack.dev.js webpack.prod.js
复制代码
webpack.common.js:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: {
index: "./src/js/index.js"
},
output: {
//[name] 输出名称等于输入名称 [contenthash:8] 八位hash
filename: "[name].[contenthash:8].js",
//你应该知道的node path 知识: http://nodejs.cn/api/path.html
path: path.resolve(__dirname, "dist")
},
module: {
rules: [
]
},
plugins: [
new HtmlWebpackPlugin({
filename: "index.html",
template: "./src/index.html"
})
]
};
复制代码
webpack.dev.js:
const merge = require("webpack-merge");
const common = require("./webpack.common.js");
module.exports = merge(common, {
mode: "development",
//开启调试
devtool: "source-map",
devServer: {
//设置基本目录结构
contentBase: "./dist",
//服务器的IP地址,可以使用IP也可以使用localhost
host: "localhost",
//服务端压缩是否开启
compress: true,
//配置服务端口号
port: 8090
}
});
复制代码
webpack.prod.js:
const merge = require("webpack-merge");
const common = require("./webpack.common.js");
module.exports = merge(common, {
mode: "production",
});
复制代码
6.修改下package.json中的script对象
"scripts": {
"dev": "webpack-dev-server --config webpack.dev.js",
"build": "rimraf dist && webpack --config webpack.prod.js"
},
复制代码
7.尝试启动服务或者打包
启动服务:
npm run dev
复制代码
打包: (rimraf dist: 打包前删除了rimraf文件夹再重新生成)
npm run build
复制代码
dist:
因为修改了配置文件每步都要重启服务比较麻烦,我们这里引入nodemon。并且添加一条命令
npm install -D nodemon
复制代码
// 监听webpack.common.js文件,有变动的话就重新启动 npm run dev
"startdev": "nodemon --watch webpack.common.js --exec npm run dev "
复制代码
package.json:
开始正式配置项目常见的功能
前面打包的文件图片可以看到只打出了index.html,这里看看怎么引入多个html
webpack.common.js: 在入口增加多一个about.js和插件多生产一个实例即可:
在根目录新建一个multi.page.js文件:
multi.page.js:
// 多入口出口处理
const path = require("path");
const fs = require("fs");
const htmlWebpackPlugin = require("html-webpack-plugin");
const pagesPath = path.resolve("./src");
var pageList = [];
function readPages() {
fs.readdirSync(pagesPath).forEach(e => {
var fullPath = pagesPath + "/" + e;
if (e.includes("html")) {
var baseName = e.slice(0, e.indexOf("."));
pageList.push({
entry: pagesPath + "\\js\\" + baseName + ".js",
chunkName: baseName,
template: pagesPath +'\\'+ e
});
}
});
return pageList;
}
// 入口
exports.getEntryPages = function() {
return readPages().reduce((r, page) => {
r[page.chunkName] = page.entry;
return r;
}, {});
};
//出口
exports.htmlPlugins = function() {
var list = readPages().map(page => {
var options = {
filename: page.chunkName + ".html",
template: page.template,
chunks: [page.chunkName]
};
return new htmlWebpackPlugin(options);
});
return list;
};
复制代码
webpack.common.js:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const multiPage = require("./multi.page");
module.exports = {
// entry: {
// index: "./src/js/index.js",
// about: "./src/js/about.js"
// },
entry: multiPage.getEntryPages(),
output: {
//[name] 输出名称等于输入名称 [contenthash:8] 八位hash
filename: "[name].[contenthash:8].js",
//你应该知道的node path 知识: http://nodejs.cn/api/path.html
path: path.resolve(__dirname, "dist")
},
module: {
rules: []
},
plugins: [
// new HtmlWebpackPlugin({
// filename: "index.html",
// template: "./src/index.html"
// }),
// new HtmlWebpackPlugin({
// filename: "about.html",
// template: "./src/about.html"
// })
...multiPage.htmlPlugins()
]
};
复制代码
就是将手动引入导出改善成nodejs自动遍历
后面就是常见功能了,先暂时写到webpack.common.js里面方便调试,最后按需切到webpack.dev.js或者webpack.prod.js
处理css(这里我以less为例)安装以下依赖
npm install -D css-loader style-loader less less-loader
复制代码
修改webpack.common.js:
module: {
rules: [
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
include: path.resolve(__dirname, "./src") // 制定路径提升性能
}
]
},
复制代码
修改index.js引入index.less,并且随意写点样式
index.html
<!DOCTYPE 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>test</title>
</head>
<body>
<div class="test">
随便写点什么 这里不要自己引入css和js 全部交给webpack来处理
</div>
</body>
</html>
复制代码
index.js:
import index from "../css/index.less";
复制代码
index.less
body {
display: flex;
background: #666;
.test {
color: #ff0;
}
}
复制代码
就会发现相关样式在head style 里了
再优化一步,将style提出来
安装依赖mini-css-extract-plugin
npm install -D mini-css-extract-plugin
复制代码
webpack.common.js 引进依赖、修改规则和产出,文件总体如下
webpack.common.js:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const multiPage = require("./multi.page");
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); //提取css文件
module.exports = {
// entry: {
// index: "./src/js/index.js",
// about: "./src/js/about.js"
// },
entry: multiPage.getEntryPages(),
output: {
//[name] 输出名称等于输入名称 [contenthash:8] 八位hash
filename: "[name].[contenthash:8].js",
//你应该知道的node path 知识: http://nodejs.cn/api/path.html
path: path.resolve(__dirname, "dist")
},
module: {
rules: [
{
test: /\.less$/,
// use: ["style-loader", "css-loader", "less-loader"],
use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
include: path.resolve(__dirname, "./src") // 制定路径提升性能
}
]
},
plugins: [
// new HtmlWebpackPlugin({
// filename: "index.html",
// template: "./src/index.html"
// }),
// new HtmlWebpackPlugin({
// filename: "about.html",
// template: "./src/about.html"
// })
...multiPage.htmlPlugins(),
new MiniCssExtractPlugin({
filename: "css/[name].[contenthash:8].css"
})
]
};
复制代码
继续优化将css前缀自动补齐
安装依赖:
npm install -D postcss-loader autoprefixer
复制代码
修改package.json:
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
复制代码
修改webpack.common.js:
--- use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
+++ use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
plugins: () => [require("autoprefixer")()]
}
},
"less-loader"
],
复制代码
最后压缩css文件
安装依赖:
npm install -D optimize-css-assets-webpack-plugin
复制代码
修改webpack.common.js:
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.css$/g,
cssProcessor: require('cssnano'), //用于优化\最小化CSS的CSS处理器,默认为cssnano
cssProcessorOptions: { safe: true, discardComments: { removeAll: true } }, //传递给cssProcessor的选项,默认为{}
canPrint: true //一个布尔值,指示插件是否可以将消息打印到控制台,默认为true
}),
复制代码
查看一下结果 源文件:
引入图片以及对图片进行压缩
npm install -D css-loader file-loader html-withimg-loader image-webpack-loader
复制代码
webpack.common.js:
{
test: /\.(svg|png|jpe?g|gif)$/i,
use: [
{
loader: "url-loader",
options: {
limit: 1,
name: "images/[name].[contenthash:8].[ext]",
publicPath: "../"
}
},
{
loader: "image-webpack-loader",
options: {
pngquant: {
quality: "70-80",
speed: 1
}
}
}
]
},
{
test: /\.html$/,
use:[
'html-withimg-loader'
]
}
复制代码
引入字体
修改webpack.common.js:
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
{
loader: "file-loader",
options: {
name: "assets/[name].[contenthash:8].[ext]",
publicPath: "../"
}
}
]
}
复制代码
babel 升级后有点小恶心..不想说了 后面再根据项目丰富css和js的提取和合并过滤