赞
踩
先向大家抛出一个问题,有没有看过jquery框架的源码?知道它源码有多少行吗?
jquery1.x版本的都在10000行以上。大家试想如果在开发时候这1万多行代码都在一个文件,那文件这么长,开发测试的时候会有多麻烦。于是乎有人就开始想了,开发的时候把代码按照不同的功能分成不同的文件,方便于开发调试,到发布的时候在把代码合并到一起就OK了,这个把代码合并到一起的玩意儿就是我们今天需要探讨的打包工具,也是它的最主要的功能之一:代码合并。
在我们前端开发中,大家一定还遇到过以下一些常见问题,诸如:
这就是今天的主角webpack要做的事情,看下去你就会知道如何使用!
1、先来看看安装:
//初始化安装目录npm init -y安装webpack和webpack-cli(4.x以上版本需要安装webpack-cli)npm install --save-dev webpacknpm install --save-dev webpack-cli
2、安装完我们来体验一下入门案例:
第一个案例总体目录如图所示:
第一步:建立src文件,在src文件下新建文件取名为index.js
//index.js内容如下console.log("hello webpack");
第二步:使用webpack打包上面的文件
npx webpack
自此变自动生成了如图所示的dist目录和打包后的main.js文件
第三步:验证打包后的main.js文件是否正确
方法一:用html文件测试,我们的例子是会在控制台输出"hello webpack"字符串
webpack
方式二:因为我们这里只用到了js代码,可以进入到打包后的文件夹,用node来运行代码
node main.js
编译后的文件默认是生产环境,代码经过压缩所以直接看不懂,如果你希望能看懂编译后的js文件,或者你希望修改一下编译后的文件名称等,可以通过给webpack提供配置文件的方式来解决:
第一步:在项目目录下建立文件webpack.config.js,文件内容如下
let path = require('path'); //webpack是node写出来的,path是node的语法 module.exports = { mode:'development', //编译环境改成是development(开发模式) entry:'./src/index.js', //需要编译的源文件目录 output:{ //编译后的目录 filename:'configTest.js', //编译后的文件名称 path:path.resolve(__dirname,'build') //编译后的路径,必须是绝对路径 }}
第二步:编译打包文件和测试生成的文件方式和上一步相同,不过注意生成的文件名称变了
npx webpack //和之前的编译方式一样
附上一张最终效果图:
问:配置文件名称能不能改?我公司的项目在打包编译的时候用的是npm run build是怎么回事?答:比如我现在将webpack配置文件名改成了webpack.configOther.js,那么我在运行的时候可以通过指定配置文件名称的方式运行,举个例子如下:
npx webpack --config webpack.configOther.js
问:上述运行代码的方式明显太长,看着很不舒服,有没有办法简化?答:我们就可以通过npm run build的方式来编译我们的代码。实现方案需要在package.json文件scripts里添加如下配置项。
//打开package.json文件,添加如下key-value值"scripts": { "build": "webpack --config webpack.configOther.js" },
上面我们测试自己写的webpack用法对不对,需要想办法运行编译后的文件才行,有没有觉得很麻烦?我们编译后的文件还需要手动在新建的html文件里面引入,每更改一次文件要想看更新后的效果都还需要在次刷新页面。。。问题多的我已经写不下去了,我们来看看解决之道吧。
webpack插件的概念:一些第三方项目工具包,webpack中引入这玩意能够对整个工程所有代码进行处理,丰富webpack的功能。
介绍了这么多我们就来实际操作一遍:
第一步:安装依赖包
//安装html-webpack-pluginnpm install --save-dev html-webpack-plugin//安装webpack-dev-servernpm install webpack-dev-server --save-dev
第二步:修改webpack.config.js文件
let path = require('path'); //webpack是node写出来的,path是node的语法let HtmlWebpackPlugin = require('html-webpack-plugin'); //HTML编译插件module.exports = { //开发环境 devServer: { contentBase: './build', //我们把编译后的目录build指定为开发环境 compress: true, //是否展示进度条 port: 9000 //开发环境启动端口 }, mode:'development', //编译环境改成是development(开发模式) entry:'./src/index.js', //需要编译的源文件目录 output:{ //编译后的目录 filename:'bundle.[hash].js', //编译后的文件名称 path:path.resolve(__dirname,'build') //编译后的路径,必须是绝对路径 }, plugins:[ new HtmlWebpackPlugin({ template:'./src/index.html', //需要编译的html源文件 filename:'indexTest.html', //编译后的文件名 minify:{ collapseWhitespace:true //编译后的html文件去掉空格 } }) ]}
上述devServer是开发环境热加载功能的部分,HtmlWebpackPlugin是自动打包html文件的插件用法,注意template是需要有一个源文件的,filename指定编译后的目标文件名称(我这里随意指定的,一般取名为index.html)
//./src/index.html源文件,我这里没有指定js文件名称 webpack
第三步:查看html-webpack-plugin编译后的效果
//编译查看效果npm run build
我在上面的配置中指定了,生成的js文件名称为hash方式,这样可以防止文件没有刷新和缓存引起的问题,我们在源html文件中并未指定生成的js文件会自动引入。
第四步:配置开发环境就像之前配置npm run build一样,我们配置一下开发环境运行方式为npm run dev
"scripts": { "build": "webpack --config webpack.config.js", "dev": "webpack-dev-server" },
接下来我们就可以通过npm run dev来开发我们的项目啦。
第五步:为了让浏览器看到效果,我们在通过js文件想html中输入一段文字
//修改我们的index.js文件document.body.innerHTML= 'devServer and HtmlWebpackPlugin';
在浏览器中输入项目路径即可访问,我们可以随意修改index.js文件的内容,保存之后页面会立即刷新最新数据。
http://localhost:9000/indexTest.html//如果生成的文件名为index.html.可省略文件名,直接用如下方式调用http://localhost:9000
开发中避免不了需要给页面添加css样式,可是webpack是node开发的,不认识css文件,我们如何让它认识呢?
有一个常接触到朋友叫loader,比如现在有一个css文件我们需要解析怎么办?这个时候我们只要在webpack中添加上style-loader css-loader就可以让webpack识别css文件了。再比如我们css用的是less语法,我们只要在webpack中添加less-loader就又可以用了。看到了吗?loader它就是用于专门处理一类文件的,功能比较单一,一种loader通常只处理一种文件。我们看下示例:
第一步:安装依赖包
//安装解析css的依赖包npm install --save-dev style-loader css-loader//安装解析less的依赖包(不用less可不安装)npm install less less-loader --save-dev
第二步:准备好样式文件
//001.css文件@import './002.css';body{ background-color: green;}//002.css文件body{ color:red;}//003.less文件body{ font-size:30px;}
第三步:要在项目中引入这些样式才能看到效果(主入口文件中引入)
//我这里的主入口文件一直都是index.js(webpack配置文件中的entry:'./src/index.js'选项)require('./001.css')require('./003.less')document.body.innerHTML= 'loader';
第四步:在配置文件中告诉webpack如何解析,添加新的属性(可参考结束语的整个配置文件)
//模块module:{ //规则:loader特点,希望单一 //loader的用法,字符串只适用于一个loader,多个loader需要用[] //loader的顺序,默认是从右向左执行 //loader还可以写出对象的方式(好处是可以添加更多的参数) rules:[ { test:/.css$/, use:[ //css-loader用于机械@import这种语法 //style-loader把css插入到页面中 { loader:'style-loader' }, 'css-loader' ] }, { test:/.less$/, use:[ 'style-loader', 'css-loader', 'less-loader' //less转换成css文件 ] } ]}
loader需要放到module下的rules中,一个项目中有各种文件需要解析,因此rules是一个数组,可以配置不同的解析规则。每一个loader配置包含test属性,是一个正则表达式用于匹配文件格式;use则用于指定具体的解析loader。
我们来查看最终的效果图:
备注:抽离css可以使用mini-css-extract-plugin
现在的前端开发避免不了要用到ES6,不过您不了解ES6和babel请跳过本部分知识。
第一步:安装相应的loader
npm install -D babel-loader @babel/core @babel/preset-env webpack
第二步:在webpack配置文件中module下rules中添加文件过滤规则
{ test:/.js$/, use:{ loader:'babel-loader', options:{ presets: ['@babel/preset-env'] //指定将ES6转换为ES5 } }}
搞定完这两步就可以在项目中使用ES6语法了,想测试的话可以将mode修改为development,然后在编译文件中查看是否有转换成ES5语法。
eslint是项目代码校验工具,能够在项目运行启动之前检查项目语法错误,如果对eslint不是很了解,请先点击链接看下相关文档
第一步:安装eslint和loader
npm install eslint eslint-loader --save-dev
第二步:在webpack配置文件中module下rules中添加文件过滤规则
{ test: /.js$/, exclude: /node_modules/, //去掉不需要校验的模块 loader: 'eslint-loader', options: { failOnError: true, },},
第三步:在项目目录下添加.eslintrc.json文件(注意文件名称前有英文点号)
//.eslintrc.json文件内容,可以根据实际需要自行配置{ "parserOptions": { "ecmaVersion": 5, "sourceType": "script", "ecmaFeatures": {} }, "rules": { "constructor-super": 2, "for-direction": 2, "getter-return": 2, "no-async-promise-executor": 2, "no-case-declarations": 2, "no-class-assign": 2, "no-compare-neg-zero": 2, "no-cond-assign": 2, "no-const-assign": 2, "no-constant-condition": 2, "no-control-regex": 2, "no-debugger": 2, "no-delete-var": 2, "no-dupe-args": 2, "no-dupe-class-members": 2, "no-dupe-keys": 2, "no-duplicate-case": 2, "no-empty": 2, "no-empty-character-class": 2, "no-empty-pattern": 2, "no-ex-assign": 2, "no-extra-boolean-cast": 2, "no-extra-semi": 2, "no-fallthrough": 2, "no-func-assign": 2, "no-global-assign": 2, "no-inner-declarations": 2, "no-invalid-regexp": 2, "no-irregular-whitespace": 2, "no-misleading-character-class": 2, "no-mixed-spaces-and-tabs": 2, "no-new-symbol": 2, "no-obj-calls": 2, "no-octal": 2, "no-prototype-builtins": 2, "no-redeclare": 2, "no-regex-spaces": 2, "no-self-assign": 2, "no-shadow-restricted-names": 2, "no-sparse-arrays": 2, "no-this-before-super": 2, "no-undef": 2, "no-unexpected-multiline": 2, "no-unreachable": 2, "no-unsafe-finally": 2, "no-unsafe-negation": 2, "no-unused-labels": 2, "no-unused-vars": 2, "no-useless-catch": 2, "no-useless-escape": 2, "no-with": 2, "require-atomic-updates": 2, "require-yield": 2, "use-isnan": 2, "valid-typeof": 2 }, "env": { "browser": true, "node": true }}
第四步:编写文件,开启项目或者编译项目检查eslint是否正确配置
//在index.js文件中添加如下代码启动项目,可以看到如图所示的错误var foo = bar;
报错:'foo' is assigned a value but never used no-unused-vars'bar' is not defined no-undef
1、JS引入图片
第一步:安装依赖loader
//图片属于文件npm install --save-dev file-loader
第二步:在配制文件中module下的rules中添加规则
{ test: /.(png|svg|jpg|gif)$/, use: 'file-loader'},
第三步:在项目目录下添加图片
import imgLogo from './0.jpg';let image = new Image();image.src = imgLogo;document.body.appendChild(image);
2、CSS中引入图片
第一步:在css中引入图片
body{ background: url('./0.jpg');}
第二步:在入口文件中引入css文件(index.js文件)
import('./001.css')
此外,html-withimg-loader可以实现html中直接使用img标签src加载图片,请自行学习~
在开发过程中,我们应该将所有图片都放到img目录下,可以通过修改上面的loader配置来实现
{ test: /.(png|svg|jpg|gif)$/, use: { loader:'file-loader', options:{ outputPath:'img/' //创建img目录 } }},
或许还会根据需要将所有文件放到么个域名下,我们可以在编译的时候,修改目录输出,添加publicPath属性即可。
//编译后的目录output:{ filename:'bundle.[hash].js', //编译后的文件名称 path:path.resolve(__dirname,'build'), //编译后的路径,必须是绝对路径 publicPath:'http://www.baidu.com/~~~~' //编译到么个域名下 },
let path = require('path'); //webpack是node写出来的,path是node的语法let HtmlWebpackPlugin = require('html-webpack-plugin'); //HTML编译插件let webpack = require('webpack');module.exports = { //开发环境 devServer: { contentBase: './build', //我们把编译后的目录build指定为开发环境 compress: true, //是否展示进度条 port: 9000 //开发环境启动端口 }, mode:'development', //编译环境改成是development(开发模式) entry:'./src/index.js', //需要编译的源文件目录 output:{ //编译后的目录 filename:'bundle.[hash].js', //编译后的文件名称 path:path.resolve(__dirname,'build'), //编译后的路径,必须是绝对路径 //publicPath:'http://www.baidu.com' }, plugins:[ new HtmlWebpackPlugin({ template:'./src/index.html', //需要编译的html源文件 filename:'index.html', //编译后的文件名 }), ], //模块 module:{ //规则:loader特点,希望单一 //loader的用法,字符串只适用于一个loader,多个loader需要用[] //loader的顺序,默认是从右向左执行 //loader还可以写出对象的方式(好处是可以添加更多的参数) rules:[ // { // test: /.js$/, // exclude: /node_modules/, //去掉不需要校验的模块 // loader: 'eslint-loader', // options: { // failOnError: true, // }, // }, { test:/.css$/, use:[ //css-loader用于机械@import这种语法 //style-loader把css插入到页面中 { loader:'style-loader' }, 'css-loader' ] }, { test:/.less$/, use:[ 'style-loader', 'css-loader', 'less-loader' //less转换成css文件 ] }, { test:/.js$/, use:{ loader:'babel-loader', options:{ presets: ['@babel/preset-env'] //指定将ES6转换为ES5 } } }, { test: /.(png|svg|jpg|gif)$/, use: { loader:'file-loader', options:{ outputPath:'img/' } } }, ] }}
本篇文章介绍webpack的入门配置,进阶配置请看webpack开发进阶篇
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。