webpack的基本概念
wepack产生的原因
传统的前端开发模式一般是开发人员直接书写html、css、和js等等各种代码,将用户请求的文件真实地放在服务器上。由于上述三种语言是弱类型语言,没有模块化概念代码不能复用,没有作用域的概念,存在变量空间污染的情况,导致传统的开发方式过程十分复杂、工作量巨大,经常要编写重复性的代码,并且各种代码互相混杂可读性差。
如果前端开发可以借鉴C++和Java等语言的模块化开发理念,将各种html、css、js和图片等资源抽象成一个个互相独立的功能模块,从而让开发人员像搭积木一样开发前端页面,就可以大大减轻开发人员工作量,并且使代码的可读性、规范性和美观性增强。
webpack如何工作
基于模块化开发需求,人们又制定了CommonJS等模块化标准,让开发者可以以模块化的方式开发,对变量、函数和各种资源进行导入导出。
但是,通过模块化方式编写的代码,浏览器是不能直接识别的,比如import、export命令和vue文件。webpack是一款打包工具,就是为了解决这个问题。它是一个node.js应用程序,利用Google V8引擎的高效能帮开发者自动处理各种依赖,把各种模块文件(js、css、图片、json等文件)打包成浏览器能够识别的代码。
webpack程序只需要指定一个入口文件即可,webpack会解析这个入口文件,寻找所有它依赖的所有文件。经过webpack打包以后,这些代码就会被转译为浏览器能识别的程序。当然,随着人们研究的深入,webpack还提供了丰富的加载器和插件,实现了babel等一些列强大的功能。
一套典型的经过webpack打包之后的最终代码由一个index.html文件、若干bundle.js文件(有可能被切割成一个个小的代码段)和资源文件夹构成。也就是说,最终呈现给用户的是这些文件。
总之,webpack让前端开发具有工程性特点,让前端开发更优雅,大大提高了开发效率。
webpack的依赖环境
node.js运行环境
npm必须安装
webpack的安装
webpack 尽量使用本地安装。 安装方法:npm install –save-dev webpack
webpack的模块化开发的主要步骤
-
编写模块库,并用CommonJS或者ES6风格导出。
// lib.js function add (num1 , num2){ return num1 + num2; } function multi(num1 , num2){ return num1 * num2; } const globalSettings = { appName: 'XX', appOpen: true } // 导出函数和变量 module.exports = { add,multi,globalSettings } -
在需要使用这些模块库方法的地方导入。例如,在math.js文件内:
const {add, globalSettings} = require('./lib.js')
console.log(add(1,3))
consoele.log(globalSettings.appName)
-
需要一个入口js文件,将所有功能模块组织起来,形成一个完成的应用,他也是使用导入的方式。一般是main.js。有点像C++ 命令行程序里的main函数。
const { add,multi } = require('./lib.js'); console.log(add(1,2)); console.log(multi(1,2)); -
目前以上程序浏览器是执行不了的。使用webpack命令打包mian.js,像是C++语言的编译语法,后面的参数可以写在
webpack.config.js里。webpack main.js obj.js这样,webpack将会自动处理
main.js程序里的依赖,自动找到需要导入的依赖(无论多复杂),然后编译出一个浏览器可以识别的脚本obj.js。 -
在实际程序中链接目标文件,就像C++的连接器,浏览器就会识别并执行obj.js里面的程序。
<script src="obj.js"></script>
webpack.config.js文件使用方式
-
webpack.config.js文件是很重要的配置文件,它是webpack命令默认调用的配置文件,因此在实际打包过程中只需要输入webpack就可以。 -
webpack.config.js文件内规定了入口文件、出口文件和其他一些重要参数。 -
webpack.config.js文件的出口文件需要用绝对路径来定位:// 先引入path包,全局包,不需要指定路径 const path = require('path'); // web.config.js实际上也是个包,需要使用模块方法输出配置信息 module.exports = { entry : './src/main.js', // 指定入口文件,不需要绝对路径 output : { // 需要使用对象的方式指定出口文件的路径 path : path.resolve(__dirname, './dist'), filename : 'bundle.js' } } -
npm run命令。它读取package.json配置文件的scripts字段记录的命令,便于记住较长或者的webpack命令。它优先调用本地程序包或者命令。例如webpack命令,可以优先调用本地webpack。
webpack的loader
-
css loader【2021.9.4在webpack 5.51.2上测试,css-loader和style-loader貌似不需要url-loader,也可以处理图片了】
先安装两个loder:
npm install –save-dev css-loader style-loader在webpack.config.js中调用loader
module.exports = { module: { rules: [ { test: /\.css$/i, // 需要用到两个loader,css-loader负责载入css文件,而style-loader负责将css加载到dom use: ["style-loader", "css-loader"], }, ], }, }; 然后运行webpack在代码中导入css // 两种方式引入 import css from './style.css'; // 或者 require('./style.css'); // 或者这种方式,比较常见 import './style.css' -
资源 loader(url)
可以在webpack.config.js中设置limit,超过这个limit的资源将会被打包成资源;没有超过的,被解析成base64字符串。[新版Webpack已经不需要这样了]
安装loader:
npm install --save-dev url-loader在webpack.config.js中调用loader:
module.exports = { module: { rules: [ test: /\.(jpg|png|gif)/, type: 'javascript/auto', //解决编译通过无法加载文件的问题 use: [ { loader: 'url-loader', options: { limit:1024, esModule:false //解决编译通过无法加载文件的问题 } } ] ]} };-
还要安装file-loader(会被url-loader自动调用)
npm install file-loader -
打包出来的文件会被放到dist文件夹,为了让index.html文件正确调用它,需要在webpack.config.js中对publicPath进行配置:
module.exports = { output:{ paht: path.resolve(__dirname,'dist'), filename: obj.js, publicPath: 'dist/' }} -
打包编译正确后,还要解决一个问题,由于Webpack5已经弃用了url-loader和file-loader,因此继续使用以上两个loader将会出现文件重复打包、无法打开的问题,要解决以上问题,需要在规则里增加两个选项,以下是该办法的完整代码:
module:{ rules:[ { test: /\.(png|jpg|gif|jpeg)$/, use: [ { loader: 'url-loader', options: { limit: 8192, esModule:false } } ], type: 'javascript/auto' } ] }
-
-
vue文件的处理
-
安装两个loader:
npm install vue-loader vue-template-compiler --save-dev -
在webpack.config.js中配置
module.exports = { module: { rules:[ { test: /\.vue$/, use: ['vue-loader'] } ] } } -
从14版本的vue-loader开始,要使用vue-loader,还需要另外配置插件,否则在打包的过程中会有错误提示。在webpack.config.js文件内配置相应的插件:
const VueLoaderPlugin = require('vue-loader/lib/plugin') module.exports = { // ... plugins:[ new VueLoaderPlugin() ] } -
让webpack支持.vue文件
.vue格式文件是Vue.js开发出来的单文件组件(SFC)格式。它将一个组件封装一个单独的文件内,不用在引号内书写模板,实现了完整而漂亮语法高亮、CommonJS 模块、组件作用域的 CSS。要使.vue文件被正常解析和运作,需要webpack等打包工具进行编译。
首先,安装vuenpm install vue –save
然后,在代码内直接导入vue:import Vue from ‘vue’
解决运行时提示错误:在webpackconfig.js的module.exports代码内中使用alias命令:
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
// 用 webpack 1 时需用 'vue/dist/vue.common.js'
} }
💡 vue 2.x 不要安装最新版本的 vue-loader。解决方案:出现提示后安装 vue-loader@15 即可。
使用webpack-dev-server搭建本地调试服务器
webpack的编译过程是比较慢的,当代码规模较大的时候,如果采取传统的调试方式,每次修改代码后,重新构建所有代码查看修改效果,是需要花费漫长的时间。更加难受的是,程序员一般习惯于修改一点代码后就要查看效果,这样反复的构建和等待,将十分烦恼。为了解决这个问题,基于node.js的express框架开发的webpack-dev-server出现了。它的运行原理是,在本地搭建一个临时服务器,将编译结果存放在内存里。调试服务器从内存读写编译结果,这就大大加快了读写速度。同时,它监听用户修改,只编译修改的部分,用户修改后就能快速、实时看到修改结果。
版本重大更新。4.0.0版本以后的webpack-dev-server的配置方式发生了较大变化,contentBase 、inline等选项不再有的,取而代之的是static对象(需要用path来拼接出绝对路径,directory属性)。inline属性不再需要了,默认是实时更新的。以下是在webpack.config.js文件内简单的配置信息:
module.exports = {
devServer: {
static: {
directory: path.join(__dirname, 'dist'),
},
port: 9923
}
}
webpack配置文件的分离
对于不同编译模式(生产模式、开发模式)下,webpack.config.js文件内所生效的配置不尽相同。为了便于管理,将不同编译模式所需要的的配置的内容进行归类。在实际编译或者调试的时候,再通过合并工具构建所需要的配置文件。当工程代码规模庞大的时候,这种分类方式是很有必要的。掌握这个知识,有利于理解脚手架的配置原理。使用方法如下:
-
首先,需要安装一个webpack-merge包。
npm install -D webpack-merge -
然后将不同配置进行抽离。将公共部分放在一个配置文件里(baseConfig.js),将体现不同特性的配置放在不同的配置文件里。在个性化配置文件内,将公共配置文件导入、合并,然后输出:
💡 要注意的是,^5.8.0版本的webpack-merge做了修改,输出的内容是对象,因此需要采取对象的方式导入,不能使用{}。使用的时候,需要用这个对方的merge方法。// 先导入工具包 const merge = require('webpack-merge') // 再导入公共配置文件 const baseConfig = require('./baseConfig.js') // 合并并输出 module.exports = merge.merge( baseConfig, devConfig) -
在package.json文件的scripts字段配置不同的命令,以显示指示webpack调用不同的配置文件,而不是调用默认的webpack.config.js。如下面的方法:"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack --config pro.config.js", "dev": "webpack-dev-server --config dev.config.js --open" },