webpack教程
Webpack在生产环境中有一个重要的作用就是减少http的请求数,就是把多个文件打包到一个js里,这样请求数就可以减少好多
一、安装
1、先装好node和npm,因为webpack是一个基于node的项目。然后npm install -g webpack webpack-cli
全局安装webpack webpack-cli
2、新建项目文件夹,比如webpack_demo,然后新建一个package.json的文件在项目根目录下
npm init //询问一些问题:按回车选择默认值 自动生成文件package.json
npm i webpack webpack-cli--D //这行命令中, i 是 install 的缩写。 --D 是 --save-dev 的缩写。
(--save-dev作用是安装的插件的同时,将插件名写入package.json的devDependencies列表中)
目前是开发环境,所以需要加上-dev,用户运行不需要依赖这个包
如果用户运行需要依赖这个包,那么就不加-dev,直接是--save,保存到生产环境
需要补充的是,刚才输入的 --save-dev 的含义是:
①将所安装的包分类到开发模式下
②将安装过的包写入到 package.json 配置文件
至此,webpack安装完成
3、在项目根目录下,建立
src源代码文件夹——开发环境dist生产环境文件夹(里面的文件都是webpack自动生成的)./当前目录../父级目录/根目录项目目录:
./index.html:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title></head><body> <script src="./dist/main.js"></script> <!-- src引入的文件将在接下来由 webpack 打包创建 --></body></html>
./src/index.js:
import {name} from './init';//引入 init.js 存于 name , (js后缀可以省略)alert(name);
./src/init.js:
var name = "newApp";export {//ECMAScript 6 语法 , 向外暴露接口供其他文件调用时使用 name//将变量 name 指定为向外暴露成员};
4、执行打包(直接打包,没有配置文件的情况下),上面多个文件文件执行打包:webpack
5、在package.json里面配置
可以在在package.json文件的"scripts"属性下增加了"build"属性,即
"build": "webpack --mode production --progress --display-modules --colors --display-reasons"
这样使用npm run build,即可执行webpack打包
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack --mode deveplopment",
"build": "webpack --mode production"
}
就可以在命令行使用npm run dev执行打包操作了
★如果是直接进行打包,而没有配置文件,那么使用npm run dev,那么会默认打包src文件夹下的index.js文件,打包完成后是main.js文件(放在dist),你有没有发现我们一开始安装webpack的时候并没有这个文件生成,所以更别提什么index.js文件了,所以这些我们需要手动创建
不管有没有使用index.js,都会打包该文件放到main.js里面,这是没有配置文件的情况下,默认入口文件是index.js,如果没有创建index.js,那么打包就会报错
如果有配置文件,那么就严格按照配置文件配置的入口文件来
我们先创建src文件,还有一个dist文件,存放默认的打包生成的文件,然后在src里再创建index.js文件
这样就可以使用npm run dev进行打包了
6、总结:
打包单个文件,直接是webpack demo.js -o demo.bundle.js --mode development 在终端(命令行)中使用webpack打包,打包哪个文件就写上其名字,后面跟上输出的名字,可以给与路径如果是打包多个文件,且彼此之间有依赖关系,就使用配置文件来进行打包webpack默认打包src文件夹下的index.js文件,如果没有对应文件和文件夹,就需要手动创建通过配置文件可以修改打包文件入口和输出文件路径7、webpack的一些相关命令
如果我们更改我们写的代码的时候,就需要重新进行打包,那就是更改一次又手动进行打包一次,那是很麻烦的,所以我们可以使用如下命令监听这个事件,源文件一更新,就会进行自动打包;一开始watch时关闭地,我需要将它打开:npx webpack --mode development --watch
注意: 这个命令只是单纯监听了默认的打包路径,也就是能监听到src下index.js的变化,也能够随将变化时进行保存刷新后其自动打包,但是,并不能监听到demo.js. 还有就是你的执行这个命令的时候,它必需属于一直监听的状态, 如果被停止了,那监听状态也停止.
二、下面介绍使用配置文件进行打包
1、创建webpack.config.js
举例:const path = require('path');module.exports = { entry: './src/index.js', //入口文件的配置项 output: { //出口文件的配置项 path: path.resolve(__dirname, 'dist'), //dist目录所在的绝对路径 filename: 'main.js' }, module: {//配置 loader 模块:例如解读CSS,图片如何转换,压缩 rules: [//相关规则写在这里 { test: /\.css$/,//正则表达式:根据后缀为 .css 的文件来匹配 css 文件 use: [//匹配搭配 css 文件后,打包时使用以下 loader 来处理文件 { loader: 'style-loader' },//loader 名称 { loader: 'css-loader',//loader 名称 options: { modules: true } } ] } ] }, plugins:[], //插件,用于生产模版和各项功能 mode: 'development' //打包模式,默认生产者模式, devServer:{} //配置webpack开发服务功能};
2、在当前目录下(package.json所在文件夹)执行:npx webpack,即可自动执行打包
3、各种参数说明:
entry:配置入口文件的地址,可以是单一入口,也可以是多入口。(html文件引入唯一的js 文件)output:配置出口文件的地址,在webpack2.X版本后,支持多出口配置。module:配置模块,主要是解析CSS和图片转换压缩等功能。plugins:配置插件,根据你的需要配置不同功能的插件。devServer:配置开发服务功能,后期我们会详细讲解。[name]的意思是根据入口文件的名称,打包成相同的名称,有几个入口文件,就可以打包出几个文件path :入口文件最终要输出到哪里,filename:输出文件的名称publicPath:公共资源路径webpack:普通打包webpack -p:压缩打包webpack -p -w:监听所有需要打包的代码,只要有代码被改动并保存后,就会自动进行打包4、如果入口文件有多个,如果output只定义一个出口文件,那么所有的入口文件都会被打包到这一个出口文件;如果想各自生成自己对应的出口文件,那么就得重新配置出口文件,如:
const path = require('path');module.exports = { entry:{ main:'./src/script/main.js', a:'./src/script/a.js' }, output: { //出口文件的配置项 path: path.resolve(__dirname, 'dist'), //dist目录所在的绝对路径 filename: '[name]-[hash]-[chunkhash].js' //[name]:名字和入口文件一样 【hash】:随机生成的本次打包的hash值 [chunkhash]:要打包文件的版本号,除非文件修改了,否则都是不变的 }};
5、打包过后的文件名是变化的,那么在index.html中引入该文件,难道每次都需要修改路径名称吗,可以使用插件来自动生成:npm install html-webpack-plugin --save-dev
在webpack.config.js中
var htmlWebpackPlugin = require('html-webpack-plugin')const path = require('path');module.exports = { entry:{ main:'./src/script/main.js', a:'./src/script/a.js' }, output: { //出口文件的配置项 path: path.resolve(__dirname, 'dist'), filename: 'js/[name]-[hash]-[chunkhash].js' , publicPath:'static' //当项目需要上线时,加上这个,那么打包后生成的js文件,前面都会加上static,如:<script type="text/javascript" src="static/js/0e8f76480769da375fb2.js"></script></body> }, plugins:[ new htmlWebpackPlugin({ template:'index.html', //以根目录下面的index.html为模板文件进行更新 filename:'index-[hash].index', //生成的html文件的名称包含hash值,自定义生成的html文件名,这样每次都会生成一个不同hash的 index文件,不建议这样使用,直接是index.html就好,默认就是index.html,可以不用设置 inject:'head', //打包后的js文件放置于头部,即</head>上面 title:'webpack is good', //设置html的title,在模板文件使用:<title><%= htmlWebpackPlugin.options.title %></title> 获取到 minify:{ //上线前压缩index.html文件 removeComments:true, //删除注释 collapseWhitespace:true //删除空格 } }) ]};
这样,就在输出路径dist下,生成了index.html(以根目录下的index为模板),并且也把打包后的js文件引入进去了,全自动,在filename后面加上js/,这样就使得js文件都打包到dist/js目录下,而html文件是直接打包到dist目录下
6、loader,和plugin不同,是专门用来处理资源文件,如转es6,less、图片压缩、图片转base64等的处理
★转es6
首先安装babel:npm install -D babel-loader babel-core babel-preset-env
然后再package.json里面配置:
"babel":{
"presets": ["env"]
}
在webpack.config.js里面配置
let htmlWebpackPlugin = require('html-webpack-plugin');const path = require('path');module.exports = { mode: "production", entry: './src/index.js', //入口文件的配置项 output: { //出口文件的配置项 ,输出路径为dist目录,即所有文件都要打包到该目录下 path: path.resolve(__dirname, './dist'), filename: 'js/bundle.js', }, module: {//配置 loader 模块:例如解读CSS,图片如何转换,压缩 rules: [//相关规则写在这里 { test: /\.js$/,//正则表达式:根据后缀为 .css 的文件来匹配 css 文件 loader:'babel-loader' } ] }, plugins:[ new htmlWebpackPlugin({ filename:'index.html', template:'index.html' }) ], //插件,用于生产模版和各项功能 mode: 'development', //打包模式,默认生产者模式, devServer:{} //配置webpack开发服务功能};
★刚刚webpack打包提示错误:
Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
解决:需要使用绝对路径。
Error: Cannot find module '@babel/core'
解决:babel-loader的版本不一样,之前的是@7.1.5版本,而现在是@8.0.0版本。所以卸载当前版本,重新安装之前的版本
★打包css文件
首先安装对应的loader,npm install style-loader css-loader --save-dev
webpack视所有资源都是一个模块,所有的资源文件都可以打包到webpack中,需要在入口文件import该资源文件
比如:入口文件是index.js,在里面 import './src/style.css'
配置webpack.config.js文件
module: {//配置 loader 模块:例如解读CSS,图片如何转换,压缩 rules: [//相关规则写在这里 { test: /\.js$/,//正则表达式:根据后缀为 .js 的文件来匹配 js 文件 loader:'babel-loader' }, { test: /\.css$/,//正则表达式:根据后缀为 .css 的文件来匹配 css 文件 loader:'style-loader!css-loader!less-loader' //css-loader使得在js里面可以处理css文件,style-loader使得js处理完的样式插入到index.html页面中 } ]},
★遇见一系列错误,以安装npm install babel-core@7.0.0-bridge.0 --save-dev结束,成功打包了css文件
★转换less文件 npm install less-loader --save-dev
创建app.less文件,在入口文件引入:import './app.less'
配置webpack.config.js文件
{ test:/\.less$/, loader:'style-loader!css-loader!less-loader' }
★打包图片文件 npm install file-loader --save-dev
1、在css文件中引入图片
配置webpack.config.js文件
{ test:/\.(png|jpg|gif|svg)$/i, loader:'file-loader' , query:{ name:'img/[hash].[ext]' }}
默认是打包到dist目录下,如果要想打包到dist/img下,可以添加query,如上所示。
【注意】要查看loader的用法,可以去https://www.npmjs.com/,搜索对应的loader查看用法
loader:'style-loader!css-loader!less-loader
loader的处理方式是从右到左,先处理less-loader,然后依次到左
★url-loader,可以处理图片和文件,当原始文件大小大于指定的值的时候,会交给file-loader处理,小于指定的值的时候,会转为base64位编码,不再是url了,而是一段编码
合理分配图片,是base64嵌入页面,还是通过http求求过来,http请求过来的图片可以缓存,base64编码不行
{ test:/\.(png|jpg|gif|svg)$/i, loader:'url-loader' , query:{ limit:20000, //即20k name:'img/[hash].[ext]' }}
★img-webpack-loader,配合file-loader、url-loader一起使用,压缩通过http请求的图片大小
{ test:/\.(png|jpg|gif|svg)$/i, loaders:[ 'url-loader?limit=20000&name=img/[hash].[ext]', 'image-webpack-loader' ]}
三、热更新
1、在webpack.config.js里面配置devServer
devServer:{
contentBase:path.resolve(__dirname,'dist') //基本目录结构,监听哪里的代码
host:'10.1.28.102', //ip地址,不建议填localhost 命令行ipconfig查看ipv4的值即是ip地址
compress:true, //服务器压缩参数,是否启用服务器压缩,一般启用
port:1717 //任何喜欢的数字
}
2、安装服务:npm install webpack-dev-server --save-dev
3、配置package.json
"scripts": {
"server": "webpack-dev-server",
},
4、运行命令:npm run server
注意:是conteneBase,不是contentPath
运行命令是npm run server,不是webpack-dev-server
四、live-server
本地开发常常需要搭建临时的服务,第一时间我们会想到用http-server。
但现在流行修改文件浏览器自动刷新hot socketing(热拔插),如live-reload。
若想浏览器自动打开项目,用opener。
现在live-server实现了三个插件的所有功能,并且很简单就能启动一个看起来很专业的本地服务
如果你比较懒,可以在package.json中增加start中增加新的脚本
"scripts": {"server": "live-server ./ --port=9090"}
然后执行 npm run server
浏览器会自动打开,并且当你修改本地文件,浏览器都会立即同步
五、案例之打包css文件
1、模块:CSS文件打包Loaders
Loaders是Webpack最重要的功能之一,他也是Webpack如此盛行的原因。通过使用不同的Loader,Webpack可以利用脚本和工具,从而对不同的文件格式进行特定处理。
注意:所有的Loaders都需要在npm中单独进行安装,并在webpack.config.js里进行配置。
Loaders的配置参数:
2、打包css文件,
首先在src文件夹下,建立一个css文件夹,在文件夹下需要打包的css文件
css文件建立好后,需要引入到入口文件中,才可以打包到,这里我们引入到entry.js中。
style-loader:用来处理css文件中的url()等
安装:npm install style-loader --save-dev
css-loader:用来将css插入到页面的style标签
安装:npm install css-loader --save-dev
两个loader都下载安装好后,我们就可以配置我们loaders了。
修改webpack.config.js中module属性中的配置代码如下(三种写法):
第一种写法:直接用use。module:{ rules:[ test:'/\.css$/', use:['style-loader','css-loader'] ]}第二种写法:把use换成loader。module:{ rules:[ test:'/\.css$/', loader:['style-loader','css-loader'] ]}第三种写法:用use+loader的写法:module:{ rules:[ { test:/\.css$/, use:[ { loader:'style-loader' }, { loader:'css-loader' } ] } ]}
9、插件配置:配置JS压缩
上线前,压缩js代码,通过使用插件的方式来实现
引入一个uglifyjs-webpack-plugin(JS压缩插件,简称uglify)。
注意:虽然uglifyjs是插件,但是webpack版本里默认已经集成,不需要再次安装,但是是需要引入的
在webpack.config.js里面引入
const uglify = require('uglifyjs-webpack-plugin');
引入后,在plugins配置里new一个uglify对象即可使用,
plugins:[ //注意是[],不是{}
new uglify() //后面不加分号,多个的话加逗号
]
最后,在终端命令行,使用webpack进行打包,压缩js文件
npm run server用在开发环境,启动服务器,是对代码进行预览的,此时的代码不需要压缩,否则无法调试
所以上面的开发完毕之后,使用下面的进行打包压缩,然后直接上线,不需要再进行热更新在调试什么的了
webpack是打包压缩,用于生产环境,打包压缩之后就上线了
webpack打包的时候发生错误:Error: Cannot find module 'uglifyjs-webpack-plugin'
执行即可npm install --save-dev html-webpack-plugin
在实际开发中,webpack配置文件是分开的,开发环境一个文件,生产环境一个文件
10、插件配置:HTML文件的发布
此时,将dist里面的index.html剪切到src目录下面,并去掉我们的JS引入代码(webpack会自动为我们引入JS),
<script src="./bundle.js" type="text/javascript" charset="utf-8"></script>
因为这才是我们真实工作的目录文件结构。
然后配置webpack.config.js文件
引入html-webpack-plugin插件
const htmlPlugin = require('html-webpack-plugin');
再进行安装该插件
npm install --save-dev html-webpack-plugin
在webpack.config.js文件,添加参数
plugins:[ new htmlPlugin({ minify:{ removeAttributeQuotes:true }, hash:true, template:'.src/index.html' })]
说明:
minify:是对html文件进行压缩,removeAttrubuteQuotes是却掉属性的双引号。如<div id="title"></div>里的双引号hash:为了开发中js有缓存效果,所以加入hash,这样可以有效避免缓存JS。template:是要打包的html模版路径和文件名称。此时,完全不需要创建dist目录,dist目录下也不需要创建任何文件,全部webpack自动
index.html文件已经被打包到我们的dist目录下了,并且自动为我们引入了路口的JS文件。
执行完webpack之后,文件已经被打包压缩了,然后执行npm run server,即可在本地查看效果
11、图片迈坑:CSS中的图片处理
第一在src目录下新建一个images文件夹,把图片放入images文件夹
第二然后安装loader:file-loader url-loader
npm install --save-dev file-loader url-loader
file-loader:解决引用路径的问题,拿background样式用url引入背景图来说,我们都知道,webpack最终会将各个模块打包成一个文件,因此我们样式中的url路径是相对入口html页面的,而不是相对于原始css文件所在的路径的。这就会导致图片引入失败。这个问题是用file-loader解决的,file-loader可以解析项目中的url引入(不仅限于css),根据我们的配置,将图片拷贝到相应的路径,再根据我们的配置,修改打包后文件引用路径,使之指向正确的文件。
url-loader:如果图片较多,会发很多http请求,会降低页面性能。这个问题可以通过url-loader解决。url-loader会将引入的图片编码,生成dataURl。相当于把图片数据翻译成一串字符。再把这串字符打包到文件中,最终只需要引入这个文件就能访问图片了。当然,如果图片较大,编码会消耗性能。因此url-loader提供了一个limit参数,小于limit字节的文件会被转为DataURl,大于limit的还会使用file-loader进行copy。第三使用loader,记得在loader使用时不需要用require引入,使用plugins才需要使用require引入。
module:{ rules:[ { test:/\.(png|jpg|gif)/, use:[{ loader:'url-loader', options:{ limit:5000 } }] } ]
}
之所以只引入url-loader,是因为url-loader已经包含了file-loader的功能
test:/.(png|jpg|gif)/是匹配图片文件后缀名称。use:是指定使用的loader和loader的配置参数。limit:是把小于500000B的文件打成Base64的格式,写入JS。12、图片迈坑:CSS分离与图片路径处理
12.1、把CSS从JavasScript代码中分离出来
第一安装extract-text-webpack-plugin插件
npm install --save-dev extract-text-webpack-plugin
第二在配置文件里引入
const extractTextPlugin = require(''extract-text-webpack-plugin);
第三在plugins配置文件里new一下
plugins:[
new extractTextPlugin('css/style.css'); //这里的css/style.css是分离后的路径位置,位于dist目录下
]
第四修改原来我们的style-loader和css-loader。
module:{ rules:[ { test:/\.css$/, use:extractTextPlugin.extract({ fallback:'style-loader', use:'css-loader' }) } ]}
利用extract-text-webpack-plugin插件很轻松的就把CSS文件分离了出来,但是CSS路径并不正确
12.2图片路径问题
第一在webpack.config.js 上方声明一个对象,叫website。
var website ={ publicPath:"http://10.1.28.102:1717/"}
第二在output选项中引用这个对象的publicPath属性。
//出口文件的配置项
output:{ //输出的路径,用了Node语法 path:path.resolve(__dirname,'dist'), //输出的文件名称 filename:'[name].js', publicPath:website.publicPath }
第三使用webpack进行打包
如何把图片放到指定的文件夹下,如images下面
修改modules里面的图片url-loader选项
modules:{ rules:[ test:'\/.(png|jpg|gif)\', options:{ limit:5000, outputPath:'/images/' } ]}
13、图片迈坑:处理HTML中的图片
第一安装 html-withimg-loadernpm install --save-dev html-withimg-loader第二配置webpack.config.js{ test:'/\.(htm|html)$/i', //注意(htm|html)加括号 use:['html-withimg-loader']}
14、给webpack增加babel支持
安装相关依赖包
npm c install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react
在webpack.config.js里面进行配置
{ test:/\.(jsx|js)$/, use:{ loader:'babel-loader', options:{ presets:[ "es2015","react" ] } }, exclude:/node_modules/}
但是不建议直接在webpack.config.js中进行配置,而是把配置写在.babelrc文件里
在项目根目录新建.babelrc文件,并把配置options写到文件里。
.babelrc //json格式 presets-渲染器{ "presets":["react","**es2015**"]}.webpack.config.js里的loader配置{ test:/\.(jsx|js)$/, use:{ loader:'babel-loader', }, exclude:/node_modules/ //不转node_modules里面的es6语法}
ENV:
现在网络上已经不流行babel-preset-es2015,现在官方推荐使用的是babel-preset-env,那我们紧跟潮流
安装最新的env
npm n install --save-dev babel-preset-env
然后修改.babelrc里的配置文件。其实只要把之前的es2015换成env就可以了。
{
"presets":["react","env"]
}
15、打包后如何调试
调试只针对于开发环境
上线前,一定要删除devtool: 'eval-source-map',然后再进行打包,否则有安全隐患
个人意见是,如果大型项目可以使用source-map,如果是中小型项目使用eval-source-map就完全可以应对,需要强调说明的是,source map只适用于开发阶段,上线前记得修改这些调试设置。
module.exports = { devtool: 'eval-source-map', entry: __dirname + "/app/main.js", output: { path: __dirname + "/public", filename: "bundle.js" }}
16、实战技巧:开发和生产并行设置
依赖dependencies
开发环境
开发依赖devDependencies
生产环境 (上线环境)
生产依赖dependencies
npm install jquery //安装到全局环境,本项目下面是没有的,如果别人拷走了,那么拷走的文件里面是不包含jquery,可能会报错
npm install jquery --save,安装到本项目下面,并且写入dependencies
拿到别人的项目,比如从github上下载下来了一个新项目,首先需要npm install进行初始化安装
会搜索package.json,搜索里面的包进行安装。如果全局里面有相关的包,那么直接就从本机全局里面拷贝,不用下载
拿到别人的项目,比如从github上下载下来了一个新项目,首先需要npm install进行初始化安装,如果只安装生产环境的包,那么就是npm install --production,而不是npm install
☆☆☆☆配置生产和开发环境并行
webpack.config.js是存在于node环境中,都是用node命令运行
局部安装webpack npm install --save-dev-webpack,webpack被安装到了项目文件夹node_modules文件夹下面
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。