前端利器前端知识点你不知道的技术

webpack教程

2019-02-14  本文已影响28人  js_hcl

一、webpack和npm的关系

  • npm是包管理器,及可以执行命令包(webpack可以看成是功能强大的命令包,除了webpack还有其它如webpack-dev-server);
  • webpack可以看成是功能强大的命令包:它还可以执行其它的功能包(装载机,插件)

二、全局安装/项目安装?[1]

重点就在这个包是否要作为CMD命令来使用及本地项目是否都差不多,因此放在全局

  1. 这个包要作为CMD命令使用:要全局安装 。如yarn cnpm webpack-dev-server等

即安装到node_global,因为node_global在系统环境中配置了路径,故而里面的脚本能在cmd中直接运行
此时这个命令的运行环境是全局环境:对应全局的webpack版本

  1. 不作为CMD命令使用:项目安装

在package.json的scripts中也可以执行命令包,此时通过npm run 命令别名来执行
因为Npm会临时把本地项目命令加载到系统环境path中,故而命令包放在本地也能通过npm run来执行
如果本地有安装,则执行本地的。否则执行的是全局的命令包。对应的执行环境webpack也是一样的。

三、打包前的准备工作(操作的webpack为3.8.1)

  • 创建项目: $ npm init
  • 全局安装webpack:$ npm install webpack -g 及脚手架$ npm install webpack-cli -g

全局安装是为了CMD使用webpack 命令

  • 本地安装webpack: $ npm install webpack --save-dev

四、js的打包

方式①:$ webpack 源文件 目标文件 即:把源文件js打包到目标文件
如:$ webpack ./src/app.js ./dist/main.js

其它参数:

  • --watch 开启热跟新
  • -p 压缩目标文件
  • -d 调试时,方便定位源文件

问题:

  • 命令行太长,写法比较复杂
  • 直接采用的是webpack命令,此时,运行环境为 全局的webpack包,并非项目的webpack版本,可能会产生和项目的一些冲突

方式②:通过配置文件,来简化webpack命令

创建配置文件 webpack.config.js
module.exports={
   entry:'./src/app.js',
   output:{
      path: __dirname + '/dist', //__dirname 是Node的变量,表示根目录。注意:path只能是绝对路径
      filename: 'main.[hash:5].js' //[hash:5]表示取hash的5位,这边是为了更新浏览器本地缓存
}
//json文件不能注释,这边是为了解释说明用的

因为webpack会自动会查找webpack.config.js,且这边已经配置好了源文件及目标文件
此时可以:$ webpack 即可打包。或$ webpack --watch

问题:

  • 命令行还是不够简洁,一些参数还是没办法配置
  • (同上)直接采用的是webpack命令,此时,运行环境为 全局的webpack包,并非项目的webpack版本

方式③:通过package.json的scripts来运行脚本

修改package.json的scripts:
"scripts": {
     "build": "webpack --watch -d",
     "prod": "webpack -p"
 }

此时,可以直接$ npm run build$ npm run prod来运行脚本

优点:

  • 命令全都由npm来运行,且命令简洁明了(便于知道有哪些命令)
  • npm来运行,所以采用的是项目的脚本(包括其它的脚本也是一样)

五、结合html

前面已经学会js的打包,但毕竟运行在浏览器的入口是html,那怎么和html结合呢?

方式①:创建html,手动引入打包后的js

问题:

  • 打包后的style,script标签要手动写入html。麻烦
  • 以及hash问题,每次生成的打包文件名还不一样,又要重新写入html。麻烦

方式②:使用html-webpack-plugin插件

安装插件
$ npm install html-webpack-plugin --save-dev 

使用插件(在webpack.config.js中引入及挂载)

引入:
const HtmlWebpackPlugin = require('html-webpack-plugin');

挂载:
plugins: [
 new HtmlWebpackPlugin({
    template:"./src/index.html", //html的模版文件
    filename: 'one.html',    //生成目标html的名字
    minify: {collapseWhitespace:true} ,//压缩html及配置压缩类型
    hash:true//会在所有注入的静态资源添加webpack每次编译产生的唯一hash值
 })
]


//hash:true的效果
<script type="text/javascript" src="main.dce13.js?dce1306176497ad4a85d"></script></body>
可以发现dce13:为main.[hash:5]生成的hash值
?dce1306176497ad4a85d为这次生成的hash值,所有静态文件都添加了这个

html-webpack-plugin详细配置点击查看
minify的详细配置点击查看


高级篇----多html的配置

  • 从实际意义出发,肯定需要配置多入口
之前entry是string类型,这次我们采用array类型

entry: {
   "entry1":'./src/app.js', //其中,"entry1"作为chunk代码块
   "entry2":'./src/app1.js',
   "entry3":'./src/app2.js',
},

使用插件
plugins: [  //tips: plugins执行顺序也是从后到前执行。即先执行底下的插件,再上面的插件
 new HtmlWebpackPlugin({
    template:"./src/index_other.html",
    filename: 'two.html',      //这个是第二个html的出口
    minify: {collapseWhitespace:true} ,
    hash:true,
    chunks:['entry2','entry3']  //这边测试处理两个,也可以通过excludeChunk:['entry1'] 取余
 }),
 new HtmlWebpackPlugin({
    template:"./src/index.html",
    filename: 'one.html',    
    minify: {collapseWhitespace:true} ,
    hash:true,
    chunks:['entry1']   //这个配置是要处理的chunk代码块,默认为all即所有入口的都处理
 })
]
--------------------------------------------------------
说明:
chunks:[] //数组内的值为entry配置里面的key值。这边即'entry1','entry2','entry3'
excludeChunk:[]//这个配置是除了数组内的chunk代码块会去处理。即取反

这边还有个问题:多个html-webpack-plugin插件处理入口,于是会生成多个目标js。

之前:
output:{
    path: __dirname + '/dist',
    filename: 'main.[hash:5].js' //多html-webpack-plugin插件时,会生成多个同名的该文件,会同名覆盖
}

改为=>
output:{
    path: __dirname + '/dist',
    filename: '[name].[hash:5].js' //name为对应entry的chunk名,同上
}

说明:[name]表示为对应entry的chunk名,同上

总结:对比一个html,区别在于:
需要多个入口,然后使用多个html-webpack-plugin插件处理入口对应的chunk,然后生成多html

六、结合css

前面学习了js的打包,以及把打包后的Js结合html,结合html我们采用插件来自动化帮我们处理一些事情。
但是怎么结合css呢,css不是浏览器入口,只能通过源js引入该css。再处理
但是webpack默认只认得js,因此要采用装载机来处理css,再放到html中。

方式①:使用'style-loader', 'css-loader' 。这种是<style>样式的方式

安装装载机
$ npm install css-loader style-loader --save-dev

使用装载机(在webpack.config.js中挂载) 相比插件不用引进

module: {
   rules: [
     {
       test: /\.css$/,    //正则表达式,匹配对应的后缀文件,然后用底下对应的装载机处理
       use: [ 'style-loader', 'css-loader' ]    //装载顺序为***从右到左***
     }
   ]
}

说明:

  • css-loader:即:编译。加载.css文件,注入到js文件中,以字符串的形式存在
  • style-loader:即:提取。使用<style>将css-loader内部样式注入到我们的HTML页面
  • css-loader/style-loader详细配置点击查看
  • 这种方式在html生成的是<style>标签

方式②:结合extract-text-webpack-plugin插件:实现css分离成文件。这种是<link>样式的方式

安装插件
$ npm install  extract-text-webpack-plugin  --save-dev

使用插件

//这边对比css-loader/style-loader的区别
module: {
  rules: [
     {
       test: /\.css$/,
       use:ExtractTextPlugin.extract({
         fallback: 'style-loader',    //提取要用到的装载机
         use: [ 'css-loader' ]    //编译要用到的装载机
       })
     }
   ]
}


以及配置plugins:

plugins{
  new ExtractTextPlugin('style.css')  //生成目标css的文件名为style.css
}

说明:

  • 通过extract-text-webpack-plugin插件实现了css的分离,而不是注入js中
  • extract-text-webpack-plugin详细配置点击查看
  • 和webpack4.0+ 不兼容
  • 这种方式在html生成的是<link>标签
  • 所以和第一种方式的优劣势对比即为:<style>和<link>样式的优劣势对比 及css有独立hash等

这边补充对于scss的css文件的处理

安装scss装载机:
$ npm install sass-loader node-sass --save-dev

方式一下使用sass-loader装载机:
module: {
   rules: [
     {
       test: /\.scss$/,    //这边匹配文件后缀为.scss
       use: [ 'style-loader', 'css-loader' ,"sass-loader"]    //只是这边后面增加该装载机
     }
   ]
}

------------------------------------------------------------------
方式二下使用sass-loader装载机:
module: {
  rules: [
     {
       test: /\.scss$/,
       use:ExtractTextPlugin.extract({
         fallback: 'style-loader',    
         use: [ 'css-loader',"sass-loader" ]    
       })
     }
   ]
}


以及配置plugins:

plugins{
  new ExtractTextPlugin('style.css')  
}

其它补充

  • 添加hash: plugins: [new ExtractTextPlugin('style.[hash:5].css')]

七、webpack-dev-server插件的使用

前面有介绍CMD命令包对于全局安装或本地安装的选择,点击回顾
方式①:全局安装 $ npm install webpack-dev-server -g
此时,在CMD即可使用该命令:$ webpack-dev-server //注意此时运行环境为全局的Webpack版本


方式②:项目安装 $ npm install webpack-dev-server --save-dev
此时可以通过配置scripts可以让npm来运行脚本

"scripts": {
  "dev": "webpack-dev-server"
}

此时,可以直接npm run dev来开启本地服务


补充

webpack.config.js中配置

devServer: {
  port: 9000,  //这边配置端口号
  open:true  //这边会自动打开浏览器
},

说明

  • 配置webpack-dev-server 运行时报错配置 Can't resolve 'webpack/hot/dev-server' 。说明项目中,没有安装webpack
  • webpack-dev-server生成的包并没有放在你的真实目录中,而是放在了内存中
  • 和webpack4.0+不兼容,这边webpack@3.8.1安装2.9.1
  • webpack-dev-server的详细配置点击查看
  • 对比webpack --watch避免了打包文件及实现了热更新

八、

# babel6配置过程

九、区分生产环境和开发环境

  • 配置部分区分
  • 方式①:在webpack.json的scripts运行脚本时,增加变量并赋值

eg:"prod": " SET NODE_ENV=production & SET hcl=huchunlin && webpack -p",
配置部分使用:console.log(process.env.NODE_ENV);console.log(process.env.hcl);
说明:process.env.变量来访问
window系统需要SET 。max系统不需要

  • 方式②:不同命令进入,即会执行不同的配置文件

eg:"prod": " webpack -p --config ./config/prod.js",
即通过--config来执行指定配置文件

  • 方式③:相结合
  • 源代码(打包后的文件)区分

通过webpack.DefinePlugin来定义源代码的全局变量。在编译时会进行替换

 webpack.config.js中=>定义全局变量
-----------------------------------------------------------------
 plugins: [
   new webpack.DefinePlugin({
     "hcl": JSON.stringify('这个是在webpack.config定义的变量')
   })
 ]

源代码中,比如在app.js中=>使用全局变量
-----------------------------------------------------------------
 console.log(hcl)
  • 配置文件和源代码都要能区分:结合①和②

  1. 二、全局安装/项目安装

上一篇下一篇

猜你喜欢

热点阅读