# webpack4-exercise **Repository Path**: finalclassic/webpack4-exercise ## Basic Information - **Project Name**: webpack4-exercise - **Description**: webpack4-exercise:常用插件、loaders,devServer,优化等 demo - **Primary Language**: JavaScript - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-12-21 - **Last Updated**: 2021-12-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: training ## README # webpack4-exercise webpack4-exercise:常用插件、loaders,devServer,优化等 demo ---- # 1.webpack是什么 打包工具(模块打包) - 打包样式 - 打包静态资源 - 打包脚本 - 打包图片 --- # 2.webpack作用 1. 打包(把多个文件打包成一个js文件--->减少服务器压力、带宽) 2. 转化(eg:less,sass,ts),通过各个loaders 3. 优化(webpack可以对项目进行优化) --- # 3.webpack 构成 1. 入口:entry 2. 出口:output 3. 加载器:loaders 4. 插件:plugins 5. 开发服务器:devServer 6. 模式:mode --- # 4.项目文件夹初始化 1. 创建src文件夹 2. 初始化package.json ```sh npm init -y ``` ------ # 5.npm **包安装** ```sh npm install {包名}@{版本号} [--save-dev] 简写:npm i --save-dev(-D):开发环境,也就是生产环境用不上的包,如webpack-dev-server --save(-S):生产环境,也就是说生产环境也需要使用的包,如jquery包 ``` ----- # 6.**webpack** ## 6.1.安装webpack,webpack-cli ```sh npm install webpack@4.14.0 webpack-cli@0.0.8-development -D ``` ## 6.2.使用 ```sh npx webpack ./src/index.js --output ./dist/bundle.js ``` ## 6.3.demo ```sh 1. 在项目中新建 dist目录 2. 在目录中新建一个index.html,并引用 bundle.js 3. 在打包生成之后,浏览器打开index.html ``` ## 6.4.使用webpack.config.js 跳转 webpack 构成 ```sh var config={ // 1. 入口:entry entry:{ }, // 2. 出口:output output:{ }, // 3. 加载器:loaders module:{ rules:[] }, // 4. 插件:plugins plugins:[ ], // 5. 开发服务器:devServer devServer:{ }, // 6. 模式:mode mode:"" } ``` ## 6.5.demo: 将npx webpack ./src/page/index/index.js --output ./dist/bundle.js以配置文件的形式来进行处理 ```sh // 1. 入口:entry entry:{ index:"./src/index.js" }, // 2. 出口:output output:{ path:path.resolve(__dirname,"dist"), filename:"bundle.js" }, ``` ## 6.6.如何使用其他名字的webpack.config.js ```sh 如自定义的配置js名称为:mywebpack.config.js,则使用方式为: npx webpack --config mywebpack.config.js ``` --- # 7.webpack 的零配置 Webpack4 增加了零配置,用于反击parcel,因而有约定默认文件夹和文件命名要求,以实现零配置。 零配置demo ```sh 1.注释掉webpack.config.js内容 2.直接运行 npx webpack //会报错 3.在src目录下新建index.js 4.再次运行 npx webpack 5.会在dist目录下生成 main.js ``` > 额外说明:上面零配置下最终生成的main.js和package.json中的main属性没有任何关系; > > package.json中的main属性指的是“包的接口模块”,或者说是入口函数-----那node_modules文件夹内的随便一个包做下解释。 > > ​ 在使用npm install进行安装包的时候,会根据该包的package.json文件的main属性来找到入口点,以此来下载该安装包的依赖,以及依赖的依赖。。。。以此类推 --- # 8.练习讲解 ## 8.1.plugins ### 8.1.1.html-webpack-plugin *需要注意下,plugin后面没有s* #### 安装 ```sh npm install -D html-webpack-plugin ``` #### 引用 ```c# const HtmlWebpackPlugin = require('html-webpack-plugin'); ``` #### 使用 ```swift plugins:[ new HtmlWebpackPlugin({ //模板地址 template:"./src/index.html", //页面标题 //head>title,需要在对应的模板页面中使用ejs语法:<%= htmlWebpackPlugin.options.title%> title:"here is index's title", //消除缓存 hash:false, //压缩输出 //OBJECT,选项见此:https://github.com/kangax/html-minifier#options-quick-reference minify:{ collapseWhitespace:false, removeAttributeQuotes:false }, //生成多个页面 filename:"index.html", //指定引入打包的块,即多页面分别按需引入js文件 chunks:["index"] }), new HtmlWebpackPlugin({ //模板地址 template:"./src/index2.html", //页面标题 //head>title,需要在对应的模板页面中使用ejs语法:<%= htmlWebpackPlugin.options.title%> title:"here is index22222's title", //消除缓存 hash:false, //压缩输出 //OBJECT,选项见此:https://github.com/kangax/html-minifier#options-quick-reference // minify:{ // collapseWhitespace:true, // removeAttributeQuotes:true // }, filename:"index2.html" }) ], ``` ### 8.1.2.clean-webpack-plugin #### 安装 ```sh npm install -D clean-webpack-plugin ``` #### 引用 ```c# const CleanWebpackPlugin = require('clean-webpack-plugin'); ``` #### 使用 ```C# new CleanWebpackPlugin(["dist"]) ``` ### 8.1.3.banner-plugin #### 安装 安装有 webpack即可,该插件已整合到webpack4中 #### 引用 ```js const webpack = require('webpack'); ``` #### 使用 ```js new webpack.BannerPlugin({ banner: "这里是bannerplugin生成的banner:'hash:[hash], chunkhash:[chunkhash], name:[name], filebase:[filebase], query:[query], file:[file]'", raw: false, // if true, banner will not be wrapped in a comment entryOnly: false, // if true, the banner will only be added to the entry chunks // test: string | RegExp | Array, // include: string | RegExp | Array, exclude: /node_modules/, }), ``` [hash],[chunkhash],[name],[filebase],[query],[file]为插件提供的占位符(关键字:placeholder) ## 8.2.devServer #### 安装 ```sh npm i -D webpack-dev-server ``` #### 配置 ```c# devServer:{ //1.设置服务器要访问的基本目录 contentBase:path.resolve(__dirname,"dist"), //∵本次培训我们将dist作为了项目的输出目录 //2.设置服务器ip地址 host:'localhost', //3.设置端口 port:8090, //4.运行的时候自动打开浏览器,也可以直接在命令行加上 "--open" //如:webpack-dev-server --open open:true, //更新时候自动刷新 inline:true, //开启HMR hot:true }, ``` #### 使用 ```sh 运行:npx webpack-dev-server ``` 对于HMR,需要在js和webpack.config.js中增加如下代码 ```c# js文件: if(module.hot){ module.hot.accept(); } ``` ```C# webpack.config.js文件: plugins:[ new webpack.HotModuleReplacementPlugin() //需要先引入webpack ] ``` ## 8.3.loaders 加载器,转化器 ### 8.3.1.处理CSS #### 使用css-loader,style-loader ##### 安装 ```sh npm i style-loader css-loader -D ``` ##### 配置 ```c# webpack.config.js module:{ rules:[ { test:/\.css$/, use:["style-loader","css-loader"] } ] }, ``` ```c# 在js文件中引入css文件 import './src/css/a.css' ``` ### 8.3.2.关于loader的写法(一共3种) ```c# module:{ rules:[ { test:/\.css$/, // use:["style-loader","css-loader"] //1 // loader:["style-loader","css-loader"] //2 use:[ //3,这种方式方便直接在loader后面指定options {loader:'style-loader'}, //指定options:{loader:'style-loader',options:{..}} {loader:'css-loader'}, ] } ] }, ``` > 解释:遇到后缀为.css的文件,webpack会先用 css-loader加载器去解析这个文件,遇到 import 等语句就将相应样式文件引入(所以没有css-loader,就没法解析这类语句),最后计算完的css,将会使用 style-loader 生成一个内容为最终解析完的css代码的style标签,放到head标签里。 *P.S.需要注意的是这里加载器在使用的时候,会从右往左一次调用(或者方式3调用的话就是从下往上)* > css文件中的内容会被写入到html页面中,渲染的顺序是根据在js中import/require的顺序来定。 ### 8.3.3.处理图片 #### 8.3.3.1.使用 url-loader,file-loader [看下webpack官方对于url-loader这个加载器的说明](https://webpack.js.org/loaders/url-loader/) > file-loader:可以解析项目中的url引入(不仅限于CSS),根据配置,将图片拷贝到相应的路径,再根据我们的配置,修改打包后文件引用路径,使之指向正确的文件。 > url-loader:如果页面图片很多,会发很多http请求,会降低页面性能。url-loader会将引入的图片进行编码,生成dataURL。相当于把图片数据翻译成了一串字符。再把这串字符嵌入到文件中,最终只需要引入这个文件就能访问图片了。当然,如果图片较大,编码会消耗性能,因此url-loader提供了一个limit参数,小于limit字节的文件会被转为dataURL,大于limit的还会使用file-loader进行拷贝。 > > P.S.因为目前版本的url-loader内部使用了file-loader,所以这2个loader需要一起安装。 ##### 安装 ```sh npm i -D file-loader url-loader ``` ##### 配置 ```c# { test:/\.(jpg|jpeg|png|gif)$/, exclude:/node_modules/, use:[ { loader:"url-loader", options:{ limit:200, } }, { loader:"file-loader", options:{ name:"[name].[ext]", outputPath:"img/" } }, ] } ``` #### 8.3.3.2.使用html-loader 主要用于处理html中的img标签的src内容 ##### 安装 ```sh npm install -D html-loader ``` ##### 配置 ```js { test: /\.html$/, use: [ { loader: 'html-loader', options: { minimize: true, removeComments: false, collapseWhitespace: false } }], } ``` > 页面使用说明: > > img:src: "./images/1.jpg":相对路径,则html-loader会对此路径进行处理。 > > img:src: "/image/1.jpg":绝对路径,则不会对该图进行处理。 ### 8.3.4.分离CSS #### 8.3.4.1.使用 extract-text-webpack-plugin 【webpack4 使用 mini-css-extract-plugin】 ##### 安装 ```sh npm i -D extract-text-webpack-plugin ``` ##### 引入 ```c# const ExtractTextWebpackPlugin = require("extract-text-webpack-plugin"); ``` ##### 配置 ```c# plugins:new ExtractTextWebpackPlugin("/css/index.css"); loaders:需要把原先 css-loader和style-loader调整下: { test:/\.css$/, // use:["style-loader","css-loader"] use:ExtractTextWebpackPlugin.extract({ fallback:'style-loader', use:'css-loader' }) }, ``` 如果直接运行打包程序,则会报错,因为webpack4下已经不建议使用该插件,但如果硬要使用则需要安装@next版本,如下,之后直接再次运行打包程序即可成功执行。 ***webpack4下,需要安装 extract-text-webpack-plugin@next*** #### 8.3.4.2.使用 mini-css-extract-plugin 【推荐】 ##### 安装 ```SH npm install mini-css-extract-plugin -D ``` ##### 引用 ```c# const MiniCssExtractPlugin = require('mini-css-extract-plugin') ``` ##### 配置 ```c# plugins: new MiniCssExtractPlugin({ filename: "css/[name].css", chunkFilename: "css/[id].css" }), module.rules: { test: /\.css$/, use: [ { loader: MiniCssExtractPlugin.loader, options: { // you can specify a publicPath here // by default it use publicPath in webpackOptions.output publicPath: '../' } }, "css-loader" ] }, ``` ### 8.3.5.使用less 注意在js中引用less文件:import '../xx/xx.less' #### 安装 ```sh npm install -D less less-loader ``` #### 配置 ```c# { test: /\.less$/, use:[ { loader: devMode?"style-loader":MiniCssExtractPlugin.loader, options: { // you can specify a publicPath here // by default it use publicPath in webpackOptions.output // publicPath: '../' } }, "css-loader", "less-loader" ] }, ``` #### less语法 ```less @a:red; @b:white; #forless { font-size: 30px; color:@a; span{ color:@b } } ``` > 个人建议在学习sass/less的时候,直接学习sass。less语法做了解即可 ### 8.3.6.使用sass #### 安装 ```sh npm install sass-loader node-sass webpack --save-dev ``` #### 配置 ```c# { test: /\.scss$/, use: [ { loader: MiniCssExtractPlugin.loader, options: { } }, "css-loader", { loader: 'postcss-loader', options: { config: { path: "./postcss.config.js" } } }, "sass-loader" ] }, ``` #### sass语法 ```scss $a:red; $b:blue; #forsass { font-size: 30px; color:$a; span{ color:$b } } ``` ### 8.3.7.前缀处理器 postcss-loader postcss不是***CSS预处理器,也不是后处理器,只是一个"插件工具"***,针对postcss有很多实用的。 postcss需要同它的插件一起使用,否则就跟没装该loader是一个样的。 [POSTCSS 插件,git文档](https://github.com/postcss/postcss#plugins) #### 安装 ```sh npm i -D postcss-loader npm install -D autoprefixer //postcss-loader插件之一:作用相当于csshack ``` #### 配置 ```c# webpack.config.js { test: /\.scss$/, use:[ { loader: MiniCssExtractPlugin.loader, options: { } }, "css-loader", //需要放在css-loader,style-loader等之前运行 //但是需要再sass,less等预处理器之后运行 'postcss-loader', "sass-loader" ] } 需要自行增加一个配置文件:postcss.config.js module.exports = { plugins: { 'autoprefixer': {}, } } //-------------也可以使用require,但是需要plugins的值此时需要用数组------------------ module.exports = { plugins: [ require('autoprefixer') ] } ``` ### 8.3.8.消除冗余CSS代码:purifycss #### 安装 ```sh npm install -D purifycss-webpack purify-css ``` #### 引用 ```c# const PurifyCSSPlugin = require('purifycss-webpack'); ``` > 需要引入一个额外的包:glob > > 安装: npm i -D glob > > 引入:const glob = require('glob'); #### 配置 ``` new PurifyCSSPlugin({ // Give paths to parse for rules. These should be absolute! paths: glob.sync(path.join(__dirname, 'app/*.html')), }) ``` ### 8.3.9.babel-loader :使用最新8.X版本(beta) > - babel:是一个ES6转码器,可以将ES6代码转换为ES5代码,从而在现有环境执行,这意味着,你可以用ES6的方式编写程序,又不用担心现有环境是否支持。 > > - babel有3个阶段:解析 ---> 转换 ---> 生成 > > - babel-loader:加载器,同其他loader一样,实现对特定文件类型的处理。(webpack本身能够处理.js文件(自身只理解JavaScript),但无法对ES2015+的语法进行转换,babel-loader的作用正是对使用了ES2015+的语法的.js文件进行处理) > > - babel-core:作用在于提供一系列的api,也就是说,当webpack使用babel-loader处理文件时,babel-loader实际上调用了babel-core的api,因此也必须安装babel-core。 #### 安装 ```sh npm install "babel-loader@next" @babel/core @babel/preset-env -D 为什么安装方式是之一的?(关键字:npm install详情请自行搜索,tips:最终效果为会生成一个独立的文件夹进行安装相关的包) ``` #### 配置 ```c# { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } ``` #### 使用 ```c# var result = [4,5,6].map(n=>n**2); //ES6 console.log("index.js:result=%o",result); ``` # 9.模块 ## 9.1 模块导出 ```js webpack.rules.js var rules = {}; module.exports = rules; ``` > 模块导出方法:module.exports = {变量/函数/其他} > > 导出的是变量,那么在使用(require)的时候就是变量;导出的是函数,那么在require的时候就是函数 ## 9.2 模块使用 ```js webpack.config.js const rules = require("./webpack.rules.js"); //需要使用相对路径的形式来引用,否则会作为node的包来查找 直接在webpack的配置中替代原先的rules modules:rules, ``` # 10. JSON的使用(git新分支@json-demo) 在webpack 3.X之前,使用json需要引入 "json-loader",从webpack3.X开始,webpack不再需要引入该包,需注意。 > 这里有个注意事项,对于json文件,在webpack.config.js中使用的时候,只能通过require的形式来导入,而在其他业务js文件中,可以通过require,也可以通过import ```JS webpack.config.js: const json = require('./myJson.json') 其他业务js:除了上面的方式外,还可以用import import json from './myJson.json'; ``` # 11. 第三方插件 ## 11.1.使用第三方插件 方法有: ​ 1.直接在js中通过require的方式来使用 ​ 2.通过externals来引用,但需要在页面上通过CDN来引用 ​ 3.在webpack.config.js中,通过webpack.ProvidePlugin({})插件来配置使用,但依然需要先安装包,但不再需要require这个包。 > 个人建议: > > 对于单个功能页面用到的第三方js库,可使用第 1 种方式 > > 对于提供CDN包的js,建议使用第 2 种方式 > > 对于需要全局使用的js,建议第 3 种 > > - 第 1 种和第 2 种方式 的差异: > - 如果在业务js中 进行了require第三方库,则不管有没有用到该库,该库都会被打包到业务js块中; > - 如果通过第 3 种方式引入的包(因为业务js不再需要require),则只要该业务js中没有用到该库,该库就不会被打包到该业务js块中去。 > - ***如果在webpack.config.js中写了 externals,则使用的包仅为cdn下的(即不会引用本地包-->也就是该第三方包不会打包到业务js中)*** 安装包(jquery为例) ```sh npm install -D jquery@1.12.4 ``` 方式1:直接在js中通过require引用,之后就可以用$这个符号来表示jQuery了 ```js const $ = require('jquery'); ``` 方式2:通过cdn引用+配置externals ```js webpack.config externals:{ "jquery":"jQuery" //注意大小写,值是"jQuery"(或者"window.jQuery") }, ``` 方式3:配置webpack.config.js ```js Plugins: new webpack.ProvidePlugin({ "$":"jquery" }), ``` ## 11.2.提取第三方js库(或者自己写的库) > 在webpack3.x 使用 CommonChunksPlugin,在4.x开始,使用 splitChunksPlugin ### webpack.config中使用 splitChunksPlugin ```js config.optimization属性中进行配置: optimization: { splitChunks: { //表示显示块的范围,有三个可选值:initial(初始块)、async(按需加载块)、all(全部块),默认为all; //chunks:'initial' (初始块:只对入口块做处理) chunks: 'async', //表示在压缩前的最小模块大小,默认为0,单位:byte; minSize: 30000,//这里表示 30Kb //表示被引用次数,默认为1 minChunks: 1, //最大的按需(异步)加载次数,默认为1; maxAsyncRequests: 5, //最大的初始化加载次数,默认为1; maxInitialRequests: 3, automaticNameDelimiter: '~', //拆分出来块的名字(Chunk Names),默认(true)由块名和hash值自动生成; //这个可以用 path/正则/方法/字符串(chunk名) name: true, //缓存组(可以覆写splitChunks.*中的配置) //优化的生效仅再满足阈值后才生效,只要有不满足的阈值,则该配置就不生效 cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true } } } } ``` --- # Q:这里生成的js文件是没有压缩过的,那么怎么样可以压缩? ```sh npx webpack --mode production 这个是在webpack 4.x版本中开始 ``` 对于 uglifyjs-webpack-plugin 这个插件,一般现在网上,尤其是百度,你能搜索到的很多关于react、vue、webpack的,都会有这么个插件: ​ ***4.X版本开始,我们没有必要再用这个插件,当然,如果你要用也没关系,效果就是"生产模式下打包"*** uglifyjs-webpack-plugin demo:各位可以实际对比下效果 ## 安装 ```sh npm install -D uglifyjs-webpack-plugin ``` ## 引用 ```sh const UglifyjsWebpackPlugin= require('uglifyjs-webpack-plugin'); ``` ## 配置 ```c# plugins中增加:new UglifyjsWebpackPlugin(), ``` # Q:下载下来的项目,无法运行 因为不包含node_modules,所以无法运行,项目下载下来后,需要执行以下命令: ```sh npm install ``` 之后,会自动根据 package.json中项,进行包安装