webpack+bootstrap+jquery+scss构建多界面项目
本文主要是介绍零构建了一个webpack4.x多页面应用程序。
1、项目初始化
建立相关的文件目录
-src
--js
--page
--public
---image
--scss
通过运行以下命令初始化 package.json :
npm init -y
安装 bootstrap和jquery
npm install bootstrap jquery
并引入 webpack 4和webpack-cli
npm i webpack --save-dev
npm i webpack-cli --save-dev
打开 package.json 并填充 script 部分,如下所示:
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production"
}
2、安装配置文件使用 babel-loader
现代 Javascript 主要是用 ES6 编写的。但并非每个浏览器都知道如何处理 ES6 。 babel-loader 是一个 webpack 的 loader(加载器),用于将 ES6 及以上版本转译至 ES5
npm i babel-core babel-loader babel-preset-env --save-dev
通过在项目文件夹中创建名为 .babelrc 的新文件来配置 Babel :
{
"presets": [
"env"
]
}
新建webpack.config.js进行配置babel-loader
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
}
};
构建src/index.js进行babel的测试,index.js的代码如下
(() => {
// let: 块级作用域
for (let i = 0; i < 3; i++) {
console.log(i) // 0 1 2
}
console.log(i) // Uncaught ReferenceError: i is not defined
})()
(() => {
// const: 常量 块级作用域
const t2 = { a: 1}
t2.a = 3
console.log(t2.a) // 3 **引用类型 存放的是地址
const t1 = 1
t1 = 2
console.log(t1) // Uncaught TypeError: Assignment to constant variable.
})()
运行npm run build命令,你会发现报以下的错,解决方法参考https://segmentfault.com/a/1190000016458913
Error: Cannot find module '@babel/core'
babel-loader@8 requires Babel 7.x (the package '@babel/core'). If you'd like to use Babel 6.x ('babel-core'), you should install 'babel-loader@7'.
at Function.Module._resolveFilename (module.js:547:15)
at Function.Module._load (module.js:474:25)
at Module.require (module.js:596:17)
at require (internal/module.js:11:18)
....
3、构建处理HTML webpack 插件
webpack需要组件来处理HTML:html-webpack-plugin 和 html-loader。
npm i html-webpack-plugin html-loader --save-dev
./src/page/index.html 中创建一个 HTML 文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>webpack</title>
</head>
<body>
<div>
aaaa
</div>
</body>
</html>
在webpack.conf.js配置相关的loader和plugn
const HtmlWebPackPlugin = require("html-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
}
]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/page/index.html",
filename: "./index.html"
})
]
};
运行 npm run build进行测试,运行成功会在dist下面生成index.html文件表示成功
4、配置入口文件集合和输出文件集合
由于要配置的是多入口文件,所有在page下面建立index.html和a.html
新建一个config.js,用来配置相关的配置,在config下建立页面集合并导出
const HTMLDirs = ['index', 'a'];
module.exports = {
HTMLDirs,
};
在webpack.config.js中生成页面集合,并用html-webpack-plugin对各个几面处理
const path = require("path");
const HtmlWebPackPlugin = require("html-webpack-plugin");
const config = require("./config/config");
let Entries = {};
// 通过 html-webpack-plugin 生成的 HTML 集合
let HTMLPlugins = [];
// 生成多页面的集合
config.HTMLDirs.forEach(page => {
const htmlPlugin = new HtmlWebPackPlugin({
filename: `${page}.html`,
template: path.resolve(__dirname, `./src/page/${page}.html`)
});
HTMLPlugins.push(htmlPlugin);
Entries[page] = path.resolve(__dirname, `./src/js/${page}.js`);
});
module.exports = {
entry: Entries,
output: {
filename: "js/[name].js",
path: path.resolve(__dirname, "dist"),
publicPath: "/"
},
plugins: [...HTMLPlugins]
};
5、构建处理SCSS的 插件
安装相关的loader插件npm i style-loader sass-loader node-sass css-loader
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: [
"style-loader",
"css-loader",
"sass-loader"
]
}
]
}
};
6、配置url-loader和file-loader
url-loader和file-loader的区别其中一个就是引用路径的问题。拿 background 样式用 url 引入背景图来说,我们都知道,webpack 最终会将各个模块打包成一个文件,因此我们样式中的 url 路径是相对入口 html 页面的,而不是相对于原始 css 文件所在的路径的。这就会导致图片引入失败。这个问题是用 file-loader 解决的,file-loader 可以解析项目中的 url 引入(不仅限于 css),根据我们的配置,将图片拷贝到相应的路径,再根据我们的配置,修改打包后文件引用路径,使之指向正确的文件。
另外,如果图片较多,会发很多http请求,会降低页面性能。这个问题可以通过url-loader解决。url-loader会将引入的图片编码,生成dataURl。相当于把图片数据翻译成一串字符。再把这串字符打包到文件中,最终只需要引入这个文件就能访问图片了。当然,如果图片较大,编码会消耗性能。因此url-loader提供了一个limit参数,小于limit字节的文件会被转为DataURl,大于limit的的时候可以用使用file-loader进行copy。
npm i html-webpack-plugin url-loader file-loader --save-dev
配置url-loader和file-loader
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
{
loader: "url-loader",
options: {
limit: 8192,
name: "[name].[ext]",
fallback: "file-loader", //超过了限制大小调用回调函数
outputPath: "public/images" //图片存储的地址
}
}
]
},
7、配置webpack-dev-server
webpack-dev-server为您提供了一个简单的Web服务器和使用实时重新加载的能力
devServer: {
contentBase: path.join(__dirname, '../src'),
},
在package.json中的script添加以下命令,就会实时监听,默认端口是8080
"start": "webpack-dev-server --open",
配置到这里基本配置基本完成,接下来是对配置文件的优化和添加相关的插件等,对项目代码进行优化。
8、通过命令行识别当前是开发模式还是生产模式
安装cross-env
cross-env能跨平台地设置及使用环境变量,大多数情况下,在windows平台下使用类似于: NODE_ENV=production的命令行指令会卡住,windows平台与POSIX在使用命令行时有许多区别(例如在POSIX,使用$ENV_VAR,在windows,使用%ENV_VAR%。。。)cross-env让这一切变得简单,不同平台使用唯一指令,无需担心跨平台问题
修改packgae.json下面的script命令
"dev": "cross-env NODE_ENV=dev webpack-dev-server --open --config webpack.config.js",
const IS_DEV = process.env.NODE_ENV === "dev"; //获取cmd命令
9、根据开发模式对输出文件和生成多页面集合进行修改
config.HTMLDirs.forEach(page => {
const htmlPlugin = new HtmlWebPackPlugin({
filename: `${page}.html`,
template: path.resolve(__dirname, `./src/page/${page}.html`),
chunks: [page, "commons"], //引入的模块,entry中设置多个js时,在这里引入指定的js,如果不设置则全部引入
favicon: path.resolve(__dirname, "./src/public/icon.ico"), //在网页窗口栏上加上图标
minify: !IS_DEV && {
collapseWhitespace: true, //清楚空格、换行符
preserveLineBreaks: true, //保留换行符
removeComments: true //清理html中的注释
}
});
HTMLPlugins.push(htmlPlugin);
Entries[page] = path.resolve(__dirname, `./src/js/${page}.js`);
});
output: {
filename: IS_DEV ? "js/[name].[hash:8].js" : "js/[name].[chunkhash:8].js",
path: path.resolve(__dirname, "dist"),
publicPath: "/"
},
contenthash、hash、chunkhash的区别
hash是跟整个项目的构建有关,只要项目里面的文件有变化,hash都会更改,并且全部项目的hash值都会一样,所以每一次构建的项目都会发生改变,不利于缓存
chunkhash是根据不同的入口文件进行依赖文件的解析、构建对应的chunk,生成对应的hash值。我们在生产环境里把一些公共库和程序入口文件区分开,单独打包构建,
接着我们采用chunkhash的方式生成哈希值,那么只要我们不改动公共库的代码,就可以保证其哈希值不会受影响。
contenthash加入index.css被index.js引用了,那index.js和index.css的哈希值是一样的,假如index.js被修改了
index.css的hash也会修改,所以这个时候就要用到我们可以使用extra-text-webpack-plugin里的contenthash值,保证即使css文件所处的模块里就算其他文件内容改变,只要css文件内容不变,那么不会重复构建。
10、安装配置mini-css-extract-plugin插件
此插件将CSS提取到单独的文件中。它为每个包含CSS的JS文件创建一个CSS文件。它支持CSS和SourceMaps的按需加载。
npm install mini-css-extract-plugin --save-d
对sass的loader进行修改
{
test: /\.scss$/,
use: [
IS_DEV ? "style-loader" : MiniCssExtractPlugin.loader, //如果是开发模式使用内嵌样式
"css-loader",
"sass-loader"
]
},
new MiniCssExtractPlugin({
filename: !IS_DEV ? "css/[name].[contenthash:8].css" : "[name].css",
chunkFilename: !IS_DEV ? "css/[name].[contenthash:8].css" : "[name].css",
allChunks: true
}),
11、安装配置clean-webpack-plugin
此插件将删除webpack output.path目录中的所有文件,以及每次成功重建后所有未使用的webpack资产,避免dist文件过去混乱。
npm install clean-webpack-plugin --save-d
new CleanWebpackPlugin(), //在构建之前清理dist文件
12、配置optimization
配置optimization可以进行手动配置和覆盖的所有优化,你可以根据不同的模式进行相关的配置对项目进行优化
optimization.minimizer
允许您通过提供不同的一个或多个自定义TerserPlugin实例来覆盖默认最小化器
terser-webpack-plugin:这个插件使用terser来缩小你的JavaScript。
optimize-css-assets-webpack-plugin: 一个Webpack插件,用于优化\最小化CSS资产。解决了extract-text-webpack-plugin的重复问题,由于extract-text-webpack-plugin仅捆绑(合并)文本块,如果它用于捆绑CSS,则捆绑包可能具有重复的条目(块可以是重复的,但是当合并时,可以创建重复的CSS)。
if (!IS_DEV) {
const TerserPlugin = require("terser-webpack-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
webpackConfig.optimization.minimizer.push(
new TerserPlugin({
parallel: true,
cache: true,
extractComments: true
}),
new OptimizeCSSAssetsPlugin({})
);
}
optimization.runtimeChunk
runtime 指的是 webpack 的运行环境(具体作用就是模块解析, 加载) 和 模块信息清单,模块信息清单在每次有模块变更(hash 变更)时都会变更, 所以我们想把这部分代码单独打包出来, 配合后端缓存策略, 这样就不会因为某个模块的变更导致包含模块信息的模块(通常会被包含在最后一个 bundle 中)缓存失效. optimization.runtimeChunk 就是告诉 webpack 是否要把这部分单独打包出来.
optimization.splitChunks
最初,块(以及在其中导入的模块)通过内部webpack图中的父子关系进行连接。CommonsChunkPlugin用于避免跨越它们的重复依赖,但是无法进一步优化。从webpack v4开始,它CommonsChunkPlugin被删除了,optimization.splitChunks代替。相关查看https://webpack.js.org/plugins/split-chunks-plugin/
splitChunks: {
chunks: "async",
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: "~",
name: true, //打包后的名称,默认是chunk的名字通过分隔符(默认是~)分隔开,如vendor~
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
name: "vendors/vendors",
reuseExistingChunk: true,
chunks: "async"
}
}
13、配置webpack.ProvidePlugin、copy-webpack-plugin、preload-webpack-plugin、css-url-relative-plugin等插件
preload-webpack-plugin:
一个Webpack插件,用于自动连接异步(和其他类型)的JavaScript块<link rel='preload'>。这有助于延迟加载。注意:这是html - webpack - plugin的扩展插件 - 这是一个简化HTML文件创建的插件,可以为您的webpack包提供服务。
webpack.ProvidePlugin
webpack配置ProvidePlugin后,在使用时将不再需要import和require进行引入,直接使用即可。
copy-webpack-plugin
将单个文件或整个目录复制到构建目录,常用来拷贝静态文件、图片等
css-url-relative-plugin
/Webpack插件将css url(...)转换为相对路径(仅支持webpack 4)。将css中的错误路劲转换为正确的路径
npm install copy-webpack-plugin preload-webpack-plugin css-url-relative-plugin --save-d
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}), //自动加载模块,当在项目中遇见$、jQuery、会自动加载JQUERY模块
new CopyWebpackPlugin([
//将单个文件或整个目录复制到构建目录。
{
from: "./src/public",
to: "public"
}
]),
new PreloadWebpackPlugin({
include: "initial"
}),
new CssUrlRelativePlugin()
https://blog.csdn.net/weixin_42298964/article/details/88552800