day-052-fifty-two-20230418-模块化开发-webpack打包
模块化开发
- 用于确保文件引入的顺序
单例设计模式
-
单例设计模式:如果有多个模块,模块之间存在依赖关系,那我们在html中导入js的时候,我们需要注意模块之间的依赖关系【模块依赖关系越复杂,就会变得很恶心】
-
例子
-
./index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <h1>11111</h1> <script src="./ModelA.js"></script> <script src="./ModelB.js"></script> <script src="./index.js"></script> </body> </html> -
./ModelA.js
let ModelA = (() => { //求和 const sum = function sum(...args) { return args.reduce((res, item) => res + item, 0); }; return { sum, }; })(); -
./ModelB.js
let ModelB = (() => { //求平均值 const average = function average(...args) { let sum = ModelA.sum(...args); return sum / args.length; }; return { average, }; })(); -
./index.js
// console.log(`ModelA-->`, ModelA); console.log(`ModelA.sum(1,2,3,4,5,6,7)-->`, ModelA.sum(1, 2, 3, 4, 5, 6, 7)); console.log(`ModelB.average(1,2,3,4,5,6,7)-->`, ModelB.average(1, 2, 3, 4, 5, 6, 7));
-
-
优点
- 兼容性好
- 依赖关系简单
-
-
普通的script标签导入关系,只适合做简单的依赖关系,复杂的如相互循环关系不行
A B C B依赖A C依赖B和A<script src="./ModelA.js"></script> <script src="./ModelB.js"></script> <script src="./index.js"></script>-
如:
A B C D B依赖A和C C依赖A和D D依赖B和C
-
AMD(require.js)
AMD是依赖于require.js的写法,不过目前2023年差不多被淘汰了。
-
AMD思想,是在单例模式的基础上,实现了依赖的管控【管控模式:依赖前置 在具体开发模块代码之前,把所有需要的依赖先处理好,再去开发】
-
依赖于其它模块并导出当前模块
define(['A', 'B'], function (A, B) { 'use strict'; return { } });
-
-
grunt、glup、fis都是基于AMD思想开发的
-
例子:
-
./index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <h1>AMD</h1> <script src="./require.min.js"></script> <script src="./index.js"></script> </body> </html> -
./ModelA.js
//导出文件--模块A不依赖于其它模块 define(function (require, factory) { "use strict"; return { sum(...args) { return args.reduce((res, item) => res + item, 0); }, }; }); -
./ModelB.js
//导出文件--模块B依赖于模块A define(["ModelA"], function (ModelA) { return { average(...args) { let sum = ModelA.sum(...args); return sum / args.length; }, }; }); -
./index.js
//导入文件,依赖于模块A与模块B require(["ModelA", "ModelB"], function (ModelA, ModelB) { console.log(`ModelA-->`, ModelA); console.log(`ModelA.sum(1,2,3,4,5)-->`, ModelA.sum(1, 2, 3, 4, 5)); console.log(`ModelB.average(1,2,3,4,5)-->`, ModelB.average(1, 2, 3, 4, 5)); });
CMD
-
CMD解决了前置依赖的问题CommonJS(后台–nodejs)/sea.js(前端)
-
nodejs --> 前端的JavaScript
- 基本上支持所有的JavaScript的语法
- 命令提示符(黑框) --> node XXX.js
-
node写法
-
./ModelA.js
//导出 单个值 module.exports = function sum(...args) { return args.reduce((res, item) => res + item, 0); }; -
./ModelB.js
let sum = require("./ModelA"); function average(...args) { let res = sum(...args); return res / args.length; } let num = 100; //导出,导出多个内容 module.exports = { average, num, }; -
./index.js
// console.log(`111-->`, 111); let path = require("path"); //node.js自身的模块 //导入,可以省略`.js`后缀,不能省略`./`(自己创建的模块);不加`./`,默认是node.js自己的模块。 // 导入单个内容 let sum = require("./ModelA"); console.log(`sum-->`, sum);//sum--> [Function: sum] console.log(`sum(1,2,3,4,5)-->`, sum(1, 2, 3, 4, 5));//sum(1,2,3,4,5)--> 15 // 导入多个内容 // let ModelB=require('./ModelB') // console.log(`ModelB-->`, ModelB); // 导入多个内容,可以使用解构赋值 let { average, num } = require("./ModelB"); console.log(`average(1,2,3,4,5)-->`, average(1, 2, 3, 4, 5));//average(1,2,3,4,5)--> 3 console.log(`num-->`, num);//num--> 100 -
要用
node.js中的node xxx命令来执行,这里在index.js所在目录中使用node index.js来调用。
-
ES6中的Module
-
在script标签中设置type=“module”,可以直接在浏览器端开启ES6Module规范,并且需要保证页面是基于HTTP/HTTPS协议预览–即本地开发要使用类似于
Live Server的本地服务器<script type="module" src="main.js"></script> -
ES6Module规范
-
模块中只想导出一次,直接基于
export default导出即可-
导出:
export default sum; export default {sum:sum}; -
导入:
import sum from './A';import A from './A'; //=> A.sum(); -
不能直接给A解构赋值
import {sum} from './A';这样报语法错误
-
-
模块中想导出多次,导出多个方法(或者变量)给外面用 export
-
导出:
export {sum};直接导出对象是不支持的,或者obj={},我们export obj这样也不支持,像这样做需要使用export default处理export let num = 10; export function fn() {}; -
导入:
import A from './A';这样写也是不行的,这种方式只支持export defaultimport {num,fn} from './A'; import * as C from './C.js'; => C.fn();
-
-
原理:浏览器底层机制,ES6中模块导出是按照
导出一个对象处理的-
基于
export导出的时候,浏览器底层机制,是按照导出一个对象处理的,每一次调用,都是设置为一个键值对。import {num,fn} from './A',导出语句如果遇到了花括号,后面导出的值就是导出对象。import * as ModelA from './A',导出语句如果遇到了*号,后面导出的值就是导出对象,as表示设置别名。
-
基于
export default导出的东西,是赋值给导出对象的default属性的。import ModelA from './A',导出语句如果没遇到花括号,后面导出的值就是导出对象.default。
-
{ // 基于 export 导出的内容,直接设置为键值对 num:10, fn(){}, // 基于 export default 导出的东西,是赋值给对象的default属性的 default:xxx }-
所以,当我们基于import的时候,如果后面是一个花括号的形式,就意为解构赋值,就是对整个模块进行解构。而如果是一个对象时,就意为接收了
模块.default这个属性。-
为啥 export default 导出的不能直接结构赋值?
-
因为它导出的内容,在对象的default属性中,我们需要先拿到default属性的值,才能解构处理…
import A from './A'; //-> 会默认让 A=`对象.default ` let {sum} = A;
-
-
为啥 export 导出的可以解构赋值?
- 因为它是直接把内容付给对象的键值对,导入的时候直接解构即可…
-
import * as X from ‘./A’; 此时它会把导出的对象赋值给X
-
-
-
例子:
-
./index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <h1>ES6 Module</h1> <script type="module" src="./index.js"></script> </body> </html> -
./index.js
//不可以省略后缀.js // import ModelA from "./ModelA.js"; // console.log(`ModelA-->`, ModelA); //注意 `export default`导出的不能直接解构赋值,但可以用一个变量A接收之后再另起一行对变量A进行解构。 //是因为底层对`export default`导出的东西放在`{default:{}}`中的`default属性`里了。 // import {sum,num} from "./ModelA.js"; // console.log(`num-->`, num); import {default as theDefault} from "./ModelA.js" console.log(`theDefault-->`, theDefault); // import {'default':{sum,num}} from "./ModelA.js"//default是关键字,会报错 // console.log(`theDefault-->`, theDefault); // import ModelA from "./ModelA.js"; // console.log(`ModelA-->`, ModelA); // let { sum, num } = ModelA; // console.log(`num-->`, num); import { average } from "./ModelB.js"; console.log(`average-->`, average); // import { a, b, c } from "./ModelC.js"; // console.log(`a, b, c-->`, a, b, c); //*表示导入全部,as表示起个别名 import * as ModelC from "./ModelC.js";//代码运行的时候,import会自动提升到顶部,所以随意写位置都可以。 console.log(`ModelC.a, ModelC.b, ModelC.c-->`, ModelC.a, ModelC.b, ModelC.c); -
./ModelA.js
//单个导出---一个js文件可以出现多次 // export // 多个导出--一个js文件只能出现一次 // export default const sum = function sum(...args) { return args.reduce((res, item) => res + item, 0); }; let num = 100; export default { sum, num, }; -
./ModelB.js
import ModelA from "./ModelA.js"; export function average(...args) { let sum = modelA.sum(...args); return sum / args.length; } -
./ModelC.js
export const a = 100; export const b = 200; export const c = 300; // 可以声明变量,值为对象 export const obj = { n: 100, m: 200, }; // export不能直接导出对象 // export { // nn:100, // mm:200 // } // 能直接导出对象的是`export default` export default { nn: 100, mm: 200, }; // `export default`可以与`export`共存,但不能出现多次,即整个js文件中只能出现一次`export default`。
-
webpack打包
-
安装webpack
-
本地安装
npm i webpack@5.49.0 webpack-cli@4.7.2-
好处:不同的文件夹可以安装不同的版本,一般就本地安装
-
本地安装之后使用的方法
-
*方法1:
-
找到 package.json —> “scripts” 配置脚本命令
- 名称可以自定义
{ "scripts": { "自定义脚本命令":"webpack" } } -
在对应目录中执行配置的脚本命令
npm run 自定义脚本命令 // npm run serve//如果package.json中的"scripts"配置的scripts下的属性名称为serve
-
-
*方法2:
-
在对应目录中执行配置的脚本命令npx webpack (webpack5版本及以上)
npx webpack
-
-
-
默认打包的js是src目录下index.js为入口文件----》dist文件夹main.js为打包后的出口文件
-
-
全局安装
npm i webpack@5.49.0 webpack-cli@4.7.2 -g //安装 npm uni webpack@5.49.0 webpack-cli@4.7.2 -g //删除-
缺点:只能安装某一个版本
-
全局安装之后可以在全局环境中的命令终端中使用命令 webpack
webpack //webpack执行
-
- webpack一般要高一个版本,webpack-cli一般要低一个版本。如果相同版本,一般会报兼容性错误。
-
-
使用webpack
-
本地安装之后使用的方法
-
*方法1:
-
找到 package.json —> “scripts” 配置脚本命令
- 名称可以自定义
{ "scripts": { "自定义脚本命令":"webpack" } } -
在对应目录中执行配置的脚本命令
npm run 自定义脚本命令 // npm run serve//如果package.json中的"scripts"配置的scripts下的属性名称为serve
-
-
*方法2:
-
在对应目录中执行配置的脚本命令npx webpack (webpack5版本及以上)
npx webpack
-
-
-
默认打包的js是src目录下index.js为入口文件----》dist文件夹main.js为打包后的出口文件
-
webpack 支持默认配置打包:不需要自己写配置项,它默认有自己的配置项,当我们执行 webpack 的时候,会按照默认配置项打包
- 找到当前项目目录中的 src文件夹,找到文件夹中的index.js文件,作为入口,按照入口文件夹中的代码和模块依赖,最后进行打包,打包后的文件,放在dist目录中
-
-
自定义webpack打包的规则
-
自己配置webpack的配置文件。如设置入口与出口
-
在根目录中新建
webpack.config.js-
当我们执行webpack命令的时候,首先检测有没有这个文件。
- 有,就按照这个文件提供的规则进行打包编译;
- 没有,就按照默认的规则进行打包编译。
-
简单的配置项示例
const path = require("path"); //node.js的路径模块 module.exports = { entry: "./src/index.js", //入口文件路径 //出口相关配置 output: { filename: "index.js", //文件名称 path: path.resolve(__dirname, "dist"), //在当前项目的根目录下,创建一个dist文件夹。 }, mode: "development", //development 开发环境-文件不会压缩,production 生产环境-会压缩 };-
实际意思,该文件是一个js文件,以node.js的方式来执行。通过module.exports抛出一个表示webpack配置对象的对象。
-
由于是node.js的文件,故而可以引入node.js的一些插件及组件,来根据不同情况做不同处理。
const path = require("path"); //node.js的路径模块 let outputPath = path.resolve(__dirname, "dist"); //在当前项目的根目录下,创建一个dist文件夹。 console.log(`打包完成后输出的目录:outputPath-->`, outputPath); // 这个导出的对象,就是webpack的配置; module.exports = { entry: "./src/index.js", //入口文件路径 //出口相关配置 output: { filename: "index.js", //文件名称 path: outputPath, //输出文件的目录 }, mode: "production", //development开发环境-文件不会压缩,production生产环境-会压缩 };
-
-
-
-
-
不同环境的配置
-
执行不同的脚本命名做不同的打包,分成开发环境和生产环境
-
方法1 做多个不同的配置执行文件,每一个配置文件对应不同的环境
-
在根目录制定做多个不同的配置执行文件,每一个配置文件对应不同的环境
-
webpack.config.development.js
const path = require("path"); let outputPath = path.resolve(__dirname, "dist"); console.log(`打包完成后输出的目录:outputPath-->`, outputPath); module.exports = { entry: "./src/index.js", output: { filename: "index.[hash].js", path: outputPath, }, mode: "development", //development开发环境-文件不会压缩,production生产环境-会压缩 }; -
webpack.config.production.js
const path = require("path"); let outputPath = path.resolve(__dirname, "dist"); console.log(`打包完成后输出的目录:outputPath-->`, outputPath); module.exports = { entry: "./src/index.js", output: { filename: "index.[hash].min.js", path: outputPath, }, mode: "production", //生产环境-会压缩 }; -
这个是公司常用的,一个配置对应一个环境,更简洁。逻辑更好理解。
-
-
在package.json中的"scripts"定义的不同执行命令中,使用
webpack --config来指定webpack的配置执行文件。
-
-
方法2 :相同的配置文件,只不过根据环境变量不同,做一些不同的配置而已。
-
使用cross-env,拿到cross-env命令执行时配置的NODE_ENV属性的值,根据NODE_ENV属性的值,对同一个配置文件进行处理。
-
安装cross-env
npm i cross-env --save-dev -
在package.json中的"scripts"定义的不同执行命令中,使用
cross-env NODE_ENV=xxxx来指定NODE_ENV的值。{ "scripts": { "开发": "cross-env NODE_ENV=development webpack", "D": "cross-env NODE_ENV=development webpack", "生产": "cross-env NODE_ENV=production webpack", "P": "cross-env NODE_ENV=production webpack", }, } -
在webpack.config.js中通过process.env.NODE_ENV拿到使用cross-env脚本执行时设置的NODE_ENV的值,并根据它对module.exports要返回出去的对象的值进行处理。
const path = require("path"); //node.js的路径模块 let outputPath = path.resolve(__dirname, "dist"); //在当前项目的根目录下,创建一个dist文件夹。 // console.log(`打包完成后输出的目录:outputPath-->`, outputPath); let NODE_ENV = process.env.NODE_ENV || `production`; const theMode = NODE_ENV; let outputFilename = `production.js`; console.log(`NODE_ENV-->`, NODE_ENV); console.log(`process.env.NODE_ENV-->`, process.env.NODE_ENV); if (NODE_ENV === `development`) { outputFilename = `development.js`; } // 这个导出的对象,就是webpack的配置; module.exports = { entry: "./src/index.js", //入口文件路径 //出口相关配置 output: { filename: outputFilename, //文件名称 path: outputPath, //输出文件的目录 }, mode: theMode, //development开发环境-文件不会压缩,production生产环境-会压缩 }; -
命令终端窗口打开调用package.json中脚本命令
npm run D
-
-
-
-
-
-
生成html文件
-
打包压缩出现html文件,将js放到html文件里。
-
安装html-webpack-plugin插件,用于在webpack中可以生成一个html文件。
npm i html-webpack-plugin -–save-dev -
在webpack.config.js中插入该插件。
// 1. 导入插件 let HtmlWebpackPlugin = require("html-webpack-plugin"); // const theHtmlWebpackPlugin = new HtmlWebpackPlugin();//默认的配置文件。 const theHtmlWebpackPlugin = new HtmlWebpackPlugin({ template: "./public/index.html", //指定自己的html文件 filename: "index.html", //生成的html的文件名称 hash: true, //给引入的文添加hash值 minify: { collapseWhitespace: true, //去掉html内容空格 removeComments: true, //去掉注释 removeAttributeQuotes: true, //去掉属性的引号 removeEmptyAttributes: true, //属性值为空的去掉 }, }); const pluginsList = []; pluginsList.push(theHtmlWebpackPlugin); module.exports = { plugins: pluginsList, //2. 使用插件,是一个数组。 } -
在package.json中scripts脚本中配置webpack命令
{ "scripts": { "build": "webpack --config webpack.config.js",//这个是打包命令,在出口文件目录产生文件 "自定义脚本命令": "webpack",//这个是打包命令,在出口文件目录产生文件 "fang": "webpack server"//这个是调用本地服务器,不会在出口文件目录产生文件 }, } -
命令终端窗口打开调用package.json中脚本命令
npm run build
-
-
配置开发服务器
-
实现热更新,浏览器自动打开,并且可以使用webpack的代理服务器
-
安装热更新插件
npm install webpack-dev-server –save-dev -
在webpack.config.js中配置代理服务器插件。
module.exports = { //配置dev-server相关的配置 devServer: { port: "8569", //端口号 host: "127.0.0.1", //域名 //compress:true,//是否开启服务器端压缩 //progress:true,//是否查看编译进度 //打开页面的路径,访问的资源路径 static: { directory: staticDirectory, //要打开页面的路径。 }, hot: true, // 是否热更新 open: true, // 是否自动打开页面 // 配置跨域代理服务器 proxy: { //代理路径1,就尽量使用这一种。表示如果fetch("/proxy/jianshu/asimov/subscriptions/recommended_collections")-->fetch("https://www.jianshu.com/asimov/subscriptions/recommended_collections"); "/proxy/jianshu/": { target: "https://www.jianshu.com", pathRewrite: { "^/proxy/jianshu/": "/" }, //路径重写。替换url,缩短原的旧标识 changeOrigin: true, //是否伪装访问源 }, //代理路径2,可以写多个。表示如果fetch("/fang/asimov/subscriptions/recommended_collections")-->fetch("https://www.jianshu.com/asimov/subscriptions/recommended_collections"); "/fang/": { target: "https://www.jianshu.com", pathRewrite: { "^/fang/": "/" }, //路径重写。替换url,缩短原的旧标识 changeOrigin: true, //是否伪装访问源 }, //代理路径3,不建议使用根路径。表示如果fetch("/asimov/subscriptions/recommended_collections")-->fetch("https://www.jianshu.com/asimov/subscriptions/recommended_collections"); "/": { target: "https://www.jianshu.com", pathRewrite: { "^/": "/" }, //路径重写。替换url,缩短原的旧标识 changeOrigin: true, //是否伪装访问源 }, }, }, }; -
在package.json中scripts脚本中配置webpack命令
{ "scripts": { "自定义脚本命令": "webpack --config webpack.config.production.js", "fang": "webpack server", "build": "webpack",//这个是打包命令,在出口文件目录产生文件 "serve": "webpack server",//这个是调用本地服务器,不会在出口文件目录产生文件,不会清除上次的出口文件 "server": "webpack server" }, } -
命令终端窗口打开调用package.json中脚本命令
npm run serve//开发环境,不会打包出结果,可以热更新 //npm run build//生产环境,会有打包结果-
可以实现的效果:
- 开发环境: 当前服务一直没有结束,当我们代码改变的时候,会自动重新编译,自动刷新浏览器,看最新的效果
- 生产环境:一直开发,等到功能效果都实现后,我们需要整体打包编译部署到服务器上,【最后把dist文件(打包后的文件),部署到服务器上即可】
-
原因:
- 经过之前的配置后,package.json中scripts脚本中
webpack server命令是打开一个本地服务器,当我们代码改变的时候,会自动重新编译,自动刷新浏览器,看最新的效果。 - 经过之前的配置后,package.json中scripts脚本中单纯的
webpack命令是把当前的文件打包到配置的出口文件目录上,以便后面部署到服务器上。
- 经过之前的配置后,package.json中scripts脚本中
-
-
-
清除旧文件
-
安装clean-webpack-plugin插件
npm i clean-webpack-plugin –save-dev -
在webpack.config.js中插入该插件。
const pluginsList = []; //"clean-webpack-plugin"用于清除之前打包后文件,再打包新的文件。 // 1. 导入插件 let { CleanWebpackPlugin } = require("clean-webpack-plugin"); const theCleanWebpackPlugin = new CleanWebpackPlugin(); pluginsList.push(theCleanWebpackPlugin); module.exports = { plugins: pluginsList, //2. 使用插件,是一个数组。 } -
在package.json中scripts脚本中配置webpack命令
{ "scripts": { "build": "webpack --config webpack.config.production.js",//这个是打包命令,在出口文件目录产生文件,配置好了clean-webpack-plugin后会清除上次的出口文件 "D": "cross-env NODE_ENV=development webpack",//这个是打包命令,在出口文件目录产生文件,配置好了clean-webpack-plugin后会清除上次的出口文件 "fang": "webpack",//这个是打包命令,在出口文件目录产生文件,配置好了clean-webpack-plugin后会清除上次的出口文件 "fang": "webpack server"//这个是调用本地服务器,不会在出口文件目录产生文件,不会清除上次的出口文件 }, } -
命令终端窗口打开调用package.json中脚本命令
npm run build
-
例子
-
./package.json
{ "name": "demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "serve": "webpack", "自定义脚本命令": "webpack", "start": "webpack --config webpack.config.development.js", "开发环境": "webpack --config webpack.config.development.js", "build": "webpack --config webpack.config.production.js", "生产环境": "webpack --config webpack.config.production.js", "开发": "cross-env NODE_ENV=development webpack", "D": "cross-env NODE_ENV=development webpack", "生产": "cross-env NODE_ENV=production webpack", "P": "cross-env NODE_ENV=production webpack", "fang": "webpack server", "server": "webpack server" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "@babel/core": "^7.14.5", "@babel/plugin-proposal-class-properties": "^7.14.5", "@babel/plugin-proposal-decorators": "^7.14.5", "@babel/plugin-transform-runtime": "^7.14.5", "@babel/preset-env": "^7.14.5", "autoprefixer": "^10.2.6", "babel-loader": "^8.2.2", "clean-webpack-plugin": "^4.0.0-alpha.0", "cross-env": "^7.0.3", "css-loader": "^5.2.6", "file-loader": "^6.2.0", "html-webpack-plugin": "^5.3.1", "html-withimg-loader": "^0.1.16", "less": "^4.1.1", "less-loader": "^9.1.0", "mini-css-extract-plugin": "^1.6.0", "optimize-css-assets-webpack-plugin": "^6.0.0", "postcss-loader": "^6.1.0", "style-loader": "^2.0.0", "terser-webpack-plugin": "^5.1.3", "uglifyjs-webpack-plugin": "^2.2.0", "url-loader": "^4.1.1", "webpack": "^5.38.1", "webpack-cli": "^4.7.2", "webpack-dev-server": "^4.6.0" }, "dependencies": { "@babel/polyfill": "^7.12.1", "@babel/runtime": "^7.14.5" }, "browserslist": [ "> 1%", "last 2 versions" ] } -
./public/index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Webpack App</title> <meta name="viewport" content="width=device-width,initial-scale=1" /> <script defer="defer" src="production.c70ae7f697e8ce258661.js"></script> </head> <body> <!-- 注释 --> <h1 class="className" id="" fang>自己的html文件</h1> <div>hot</div> </body> </html> -
./src/index.js
import obj from "./modelA.js"; console.log(obj.sum(1, 2, 3, 4)); import { average } from "./modelB.js"; console.log(average(1, 2, 3, 4)); console.log("111111"); //简书,跨域代理 fetch("/asimov/subscriptions/recommended_collections") .then((response) => { return response.json(); }) .then((value) => { console.log(value); }); fetch("/fang/asimov/subscriptions/recommended_collections") .then((response) => { return response.json(); }) .then((value) => { console.log("66666fang", value); }); -
./src/modelA.js
const sum=function sum(...params){ return params.reduce((result,item)=>{ return result+item; }) } export default { sum } -
./src/modelB.js
import obj from "./modelA.js"; export const average= function average(...params){ let total=obj.sum(...params); return total/params.length; } -
./webpack.config.js
const path = require("path"); //node.js的路径模块 let outputPath = path.resolve(__dirname, "dist"); //在当前项目的根目录下,创建一个dist文件夹。 // console.log(`打包完成后输出的目录:outputPath-->`, outputPath); let NODE_ENV = process.env.NODE_ENV || `production`; const theMode = NODE_ENV; let outputFilename = `production.js`; console.log(`NODE_ENV-->`, NODE_ENV); console.log(`process.env.NODE_ENV-->`, process.env.NODE_ENV); if (NODE_ENV === `development`) { outputFilename = `development.js`; } // 1. 导入插件 let HtmlWebpackPlugin = require("html-webpack-plugin"); // const theHtmlWebpackPlugin = new HtmlWebpackPlugin();//默认的配置文件。 const theHtmlWebpackPlugin = new HtmlWebpackPlugin({ template: "./public/index.html", //指定自己的html文件 filename: "index.html", //生成的html的文件名称 hash: true, //给引入的文添加hash值 minify: { collapseWhitespace: true, //去掉html内容空格 removeComments: true, //去掉注释 removeAttributeQuotes: true, //去掉属性的引号 removeEmptyAttributes: true, //属性值为空的去掉 }, }); const pluginsList = []; pluginsList.push(theHtmlWebpackPlugin); //清除之前打包后文件,再打包新的文件。 let { CleanWebpackPlugin } = require("clean-webpack-plugin"); const theCleanWebpackPlugin = new CleanWebpackPlugin(); pluginsList.push(theCleanWebpackPlugin); let staticDirectory = path.join(__dirname, "dist"); // 这个导出的对象,就是webpack的配置; module.exports = { entry: "./src/index.js", //入口文件路径 //出口相关配置 output: { filename: outputFilename, //文件名称 path: outputPath, //输出文件的目录 }, mode: theMode, //development开发环境-文件不会压缩,production生产环境-会压缩 plugins: pluginsList, //2. 使用插件,是一个数组。 //配置dev-server相关的配置 devServer: { port: "8569", //端口号 host: "127.0.0.1", //域名 //compress:true,//是否开启服务器端压缩 //progress:true,//是否查看编译进度 //打开页面的路径,访问的资源路径 static: { directory: staticDirectory, //要打开页面的路径。 }, hot: true, // 是否热更新 open: true, // 是否自动打开页面 // 配置跨域代理服务器 proxy: { //代理路径1,就尽量使用这一种。表示如果fetch("/proxy/jianshu/asimov/subscriptions/recommended_collections")-->fetch("https://www.jianshu.com/asimov/subscriptions/recommended_collections"); "/proxy/jianshu/": { target: "https://www.jianshu.com", pathRewrite: { "^/proxy/jianshu/": "/" }, //路径重写。替换url,缩短原的旧标识 changeOrigin: true, //是否伪装访问源 }, //代理路径2,可以写多个。表示如果fetch("/fang/asimov/subscriptions/recommended_collections")-->fetch("https://www.jianshu.com/asimov/subscriptions/recommended_collections"); "/fang/": { target: "https://www.jianshu.com", pathRewrite: { "^/fang/": "/" }, //路径重写。替换url,缩短原的旧标识 changeOrigin: true, //是否伪装访问源 }, //代理路径3,不建议使用根路径。表示如果fetch("/asimov/subscriptions/recommended_collections")-->fetch("https://www.jianshu.com/asimov/subscriptions/recommended_collections"); "/": { target: "https://www.jianshu.com", pathRewrite: { "^/": "/" }, //路径重写。替换url,缩短原的旧标识 changeOrigin: true, //是否伪装访问源 }, }, }, }; -
./webpack.config.development.js
const path = require("path"); let outputPath = path.resolve(__dirname, "dist"); console.log(`打包完成后输出的目录:outputPath-->`, outputPath); module.exports = { entry: "./src/index.js", output: { filename: "index.[hash].js", path: outputPath, }, mode: "development", //development开发环境-文件不会压缩,production生产环境-会压缩 }; -
./webpack.config.production.js
const path = require("path"); let outputPath = path.resolve(__dirname, "dist"); console.log(`打包完成后输出的目录:outputPath-->`, outputPath); module.exports = { entry: "./src/index.js", output: { filename: "index.[hash].min.js", path: outputPath, }, mode: "production", //生产环境-会压缩 };