慕课笔记--[课程]webpack深入与实战

来源:互联网 发布:手机怎么找到淘宝客服 编辑:程序博客网 时间:2024/05/21 18:36

一、webpack可以实现的功能

可以打包 AMD、CMD、Common、css\、coffee、json、Image 等均可打包,也可以打包自定义后缀的文件,如:.vue、.jsx 等,都可以通过loaders加载器进行处理打包。
目前webpack+react+es6 的组合非常常见。
特性:
(1)、将js、css等文件视为一个模块,将外部或者第三方文件也视为一个模块(2)、实现按需加载,是浏览器能够在最短时间打开项目(3)、适合大型项目操作
二、webpack的目标

(1). 其他打包工具不具备的代码分割,切分依赖库,分开加载所需的依赖,使加载速度加快。(2). 全面的loaders加载系统(3). 插件系统,如模块热更新
三、webpack的安装与命令行指令
信息说明:
(1)、在 webpack 2中 指定的 loader 要使用双引号 
webpack hello.js hello.bundle.js --module-bind "css=style-loader!css-loader"  //绑定css的loader
(2)、webpack -g  //查看webpack命令
(3)、css-loader使得webpack可以处理.css 文件。
style-loader将css-loader处理完的文件新建一个<style>插入到HTML里
npm install css-loader style-loader -save-dev //下载用于适配css文件的loader
(4)、npm install webpack --save-dev     //下载webpack
npm init // 在项目中引导创建一个package.json文件安装包的信息可保持到项目的package.json文件中,以便后续的其它的项目开发或者他人合作使用,也说package.json在项目中是必不可少的。
(5)、style.loader!css.loader 意思是!前模块依赖!后模块,就是style依赖css
(6)、我想看到打包过程,可以使用--progress, 在此我们可以看到一个百分比读条
webpack hello.js hello.bundle.js --module-bind "css=style-loader!css-loader" -progress
(7)、每一次在命令行输一次命令行命令,十分的繁琐,可以使用--watch使它自动更新,自动打包。
(aSuncat: css-loader后面不要加!,mac下是单引号'',windows是双引号"")
webpack hello.js hello.bundle.js --module-bind "css=style-loader!css-loader" -watch
(8)、webpack支持的三种模块化方式:md,commonJs, es6.require(‘.world.js’)的写法是commonJs的(9)、webpack天生不支持css类型的文件,如果要处理这种文件,就要依赖css.loader。
而如果要在html中引入css样式需要style.loader将样式通过style标签插入到head标签中。
(10)、在使用require加载css模块时要引进style-loader(使样式以嵌入的形式插入页面)和css-loader(识别css文件):require('style-loader!css-loader!./style.css');
完整的步骤:
(1)、cd 进入一个目录(2)、mkdir webpack-test(3)、cd webpack-test(4)、npm init(5)、npm install webpack --save-dev
(6)、npm install css-loader style-loader -save-dev //下载用于适配css文件的loader
(7)、webpack hello.js hello.bundle.js --module-bind "css=style-loader!css-loader" --watch  --progress
其他参数:
--display-reasons //打包原因
--progress -dispaly-modules //列出打包模块
--progress  //查看打包过程
--watch //文件更新时自动打包
--colors: 显示颜色
打包过程中信息解析:
我们会看到hash值,webpack的版本号,打包的时间,Asset是指这次打包生成的文件,
Size是指文件的大小,Chunks是指这次打包的方块,Chunk name是指这次打包的块名称
三、建立项目的webpack配置文件(一)
1、信息说明:
(1)、webpack 命令直接默认执行 webpack.config.js 文件。如果要更改 则使用 --config  webpack --config webpack.dev.js
(2)、webpack.config.js 文件在 window的配置中webpack的 path 应该加上绝对的路径。推荐使用绝对路径,防止不同版本的冲突
var path = require("path")    //webpack2需要先引入path
module.exports = { //输出
entry: '/src/script/main.js', //指定打包的入口文件, string 单独入口 | object 多个入口多个文件 | array 多个入口合并在一个文件中
output: { //指明打包以后的文件放在什么地方
path: path.resolve(__dirname , '/dist/js/'),
filename: 'bundle.js' //指定打包以后的文件名叫什么
}}
备注1:如果你的entry是多余一个的,那么你可以使用一些占位符保证你输出的文件名是唯一的。
output的filename这些占位符有三个[name]表示chunk的的name,也就是chunk的key[hash] 是每次打包的hash[chunkhash] 每个模块自己的hash值,可以理解为版本号,也理解为md5值(保证每个文件的唯一性)
备注2:entry入口文件有三种定义方式:# 单独定义一个文件# 将两个或多个平行文件定义在一个数组中,它们会被打包为一个文件# 将两个或多个文件定义在一个对象中,它们会被分别打包
(3)、如果是webpack.config.js改名字,改成webpack.dev.config.js终端目标文件输入:webpack会失效终端目标文件输入:webpack --config webpack.dev.config.js会生效(4)、package.json中的scripts中写入webpack的参数后,
eg:  "webpack":"webpack --config web pack.config.js  --color --progress "终端目标文件输入:npm run webpack
(5)、 js文件中如果要引入css等其他文件,需要使用loader,有三种引用方式:# 直接在引入文件路径前加loader名称,例如:require('style-loader!css-loader!./style.css'); #在命令行里加:webpack entry.js bundle.js --module-bind 'css=style-loader!css-loader';# 在配置文件中加:loaders: [{test: /\.css$/,loader: 'style-loader!css-loader'}]
四、webpack配置文件(二)
1、针对多页面应用
entry使用一个对象 {
path1: ‘./script/main.js’,
a: ‘./script/a.js’
},
output: {
path: ‘./dist/js’,
filename: ‘[name].[hash].js’
// [name] path1 和 a ,[hash] 本地打包的md5值 没有修改的部分hash值不会改变,起到增量修改,不重新加载浏览器缓存过的没有修改文件}
2、entry三种输入方式(1)string,输入字符串    entry:{        main:'./src/script/main.js'    },(2)array, 数组。适用情况:两个平行的,不相依赖的文件打包在一起。    entry:{        main:['./src/script/main.js','./src/script/a.js']    },(3)object, 适用情况:多页面应用程序。这里要和output里的[name]占位符配合使用,威力才能最大。如果你要打包成多个js文件,那么entry对象里的key叫做chunk就是文件名,里面的值就是需要打包的文件里面包含的文件。    entry:{        main:'./src/script/main.js',        a:'./src/script/a.js'    },3、output占位符有3种:[name]、[hash]、[chunkhash]output的filename(1)hash: 这次打包的hash每次终端运行webpack命令,都会生成一段信息,这段信息的第一行就有一个hash(2)chunkhash:每一个chunk自己的hash五、自动化生成项目中的html页面(一)
针对每次修改js文件之后,[hash]占位符就会改变,在index.html引用中,每次都要更改文件名的繁琐工作,可以利用插件解决:
1. 命令窗口输入:npm install html-webpack-plugin --save-dev2. 在配置文件webpack.config.js中引用插件(commonjs模块写法):var htmlWebpackPlugin = require('html-webpack-plugin');3. 在插件属性中初始化plugin:module.exports = {    plugins:[        new htmlWebpackPlugin()    ]}
这里的代码只会让webpack自动生成一个index.html,里面自动把js代码插入到index.html当中。//注意,这里说的是webpack生成的index.html,不是你自定义的index.html。4. 再打包一次:在命令窗口输入npm webpack run5. 生成的index.html文件就能自动引用之前生成的两个js文件6. 让两个ndex.html建立联系:在plugins的设置中加入模板参数:module.exports = {    plugins:[        new htmlWebpackPlugin({                template: 'index.html' //此时上下文环境默认在根目录下,是你自己写的文件       })    ]}7. 让生成的js和html文件放在不同的文件夹下:修改output参数   output:{        path: path.resolve(__dirname, 'dist'),   //打包后的存放路径        filename:'js/[name]-[chunkhash].js',   //增加一个相对路径
publicPath:'http://cdn.com'                //设置上线地址
    },8. 插件的其它参数:plugins:[        new htmlWebpackPlugin({            filename:'index-[hash].html',  //文件名            template:'index.html',  //传参,让两个html文件建立联系            inject:'head',  //让生成的script标签放在head标签还是body标签中
    title: 'i am back',  //html中的title要取到这个值,需要写成:<title><%= htmlWebpackPlugin.options.title %></title>
    date: new Date(),   //html中的date要取到这个值,需要写成:<div><%= htmlWebpackPlugin.options.date %></div>
    chunks: [ ' main', ' '],// 可以用于htmlWebpackPlugin.files.chunks[’main’].entry 就可以拿到chunk main生成的文件名称
    excludeChunks: [' ', ' '],//排除那些chunk在html模板中被拿到
    minify: {     //压缩当前生成的html文件, 在plugins中添加minify属性
           removeComments:true       //删除注视         collapseWhitespace: true   //删除空格
    }           })    ]
五、自动化生成项目中的html页面(二)
1、参数中传参,模板中引用config中的title设置,然后对index.html中用<%= %>进行取值<%= %>表示:需要对什么进行取值一般引用htmlWebpackPlugin里的值,直接htmlWebpackPlugin.options.title。2、index.html中遍历:<!--遍历:得到的htmlWebpackPlugin的key是files和options,再分别对这两个key进行遍历-->    <% for (var key in htmlWebpackPlugin.files){ %>        <%= key %>:<%= JSON.stringify(htmlWebpackPlugin.files[key]) %>    <% } %>    <% for (var key in htmlWebpackPlugin.options){ %>        <%= key %>:<%= JSON.stringify(htmlWebpackPlugin.options[key]) %>    <% } %>注:JSON.stringify(htmlWebpackPlugin.files[key])对这一对象的内容字符串化3、htmlWebpackPlugin.files.chunks[’main’].entry 就可以拿到chunk main生成的文件名称。4、https://www.npmjs.com中搜索html-webpack-plugin可以看到对插件的详细解释5、path:输出的时候把所有文件都放到合格目录下, 设置上线地址:在output中添加publicPath属性.publicPath:占位符,需要上线,设置时,如果设置为http://cdn.com,这样js的路径就会替换为绝对地址以http://cdn.com开头的路径,这样就能满足上线需求了。6、压缩当前生成的html文件:在plugins中添加minify属性https://www.npmjs.com,输入html-webpack-plugin,然后搜索minify,找到html-minify的链接点进去,能看到minify的参数列表。(1).  removeComments:true   //删除注视(2). collapseWhitespace: true   //删除空格
7、完整index.html ejs模板
<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title><%= htmlWebpackPlugin.options.title %></title>
  //在模板文件中获取webpack中entry的路径的  <script type="text/javascript" src="<%= htmlWebpackPlugin.files.chunks.main.entry %>">  </script>  <script type="text/javascript" src="<%= htmlWebpackPlugin.files.chunks.a.entry %>">  </script></head><body>  <%= htmlWebpackPlugin.options.date%>  <!--<% for(var key in htmlWebpackPlugin.files){%>    <%= key%> : <%= JSON.stringify(htmlWebpackPlugin.files[key])%>  <%}%>  <% for(var key in htmlWebpackPlugin.options){%>    <%= key%> : <%= JSON.stringify(htmlWebpackPlugin.options[key])%>  <%}%>--></body></html>
六、自动化生成项目中的html页面(三)
1、多页面如何引用属于自己的js文件,可以借助htmlwebpackplugin配置chunks
2、如果想用不同的模版生成不同的html文件,只用在plugins里添加各种htmlWebpackPlugin的实例就好了。
3、页面中引入inline的script
github上,ampedandwired/html-webpack-plugin/examples/inline/template.jade中可以看到代码。
4、htmlWebpackPlugin.files.chunks.entry就是chunks输出的地址
5、main以inline的形式引进,a,b,c以外链的形式引进
6、index.html中
(1)在htmlWebpackPlugin的配置中有一个有一个参数chunks可以配置。
(2)head中
<script type="text/javascript">
        <%= compilation.assets[htmlWebpackPlugin.files.chunks.main.entry.substr(htmlWebpackPlugin.files.publicPath.length)].source() %>
</script>
重点:!!!compilation.assets是webpack暴露出来可以获取文件数据的方法。通过传文件名路径进这个对象,拿到这个文件的索引,通过调用source拿到文件内容。
compilation.assets需要的是不带publicPath,htmlWebpackPlugin.files.chunks.main.entry带publicPatch,所以用substr()截取。
(3)body中
    <% for (var k in htmlWebpackPlugin.files.chunks){ %>        <% if(k!='main') %>            <script type="text/javascript" src="<%= htmlWebpackPlugin.files.chunks[k].entry %>"></script>        <% } %>    <% } %>(4)config.js中inject为false7、小结(1)、html和动态生成的文件一一对应。(2)、htmlWebpackPlugin,如何自定义html,并且通过模板,参数如何传参。(3)、多页面时,如何通过htmlWebpackPlugin生成多个html(4)、深入探究通过htmlWebpackPlugin,结合模板的方式把生成的js,通过inline引入到html中
8、完整index.html  ejs模板
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title><%= htmlWebpackPlugin.options.title %></title>
  //在模板文件中获取webpack中entry的路径的
  <script type="text/javascript" src="<%= compilation.assets[htmlWebpackPlugin.files.chunks.main.entry.substr(htmlWebpackPlugin.files.publicPath.length)].source() %>">
  </script>
</head>
<body>
<% for (var k in htmlWebpackPlugin.files.chunks){ %>        <% if(k!='main') %>            <script type="text/javascript" src="<%= htmlWebpackPlugin.files.chunks[k].entry %>"></script>        <% } %>
<% } %></body></html>
七、什么是 Loader 以及 Loader 的特性 
1、新建一个组件(component),layer有自己的模版文件和css文件还有js文件。然后用export default导出去可以给别人调用。这都是es6的写法。2、loader可以生成额外的文件.(外注:Webpack 本身只能处理原生的 JavaScript 模块,但是 loader 转换器可以将各种类型的资源转换成 JavaScript 模块。这样,任何资源都可以成为 Webpack 可以处理的模块。)3、进入webpack网站的user loaders:使用loader的三种方式(1)、require的路径前面加loader!(2)、直接配置配置文件loaderstest:对资源的正则匹配,如果匹配到Loader,就会对其进行处理。(3)、直接使用cliwebpack --module-bind jade --module-bind 'css=style!css',指定了2个loader,先是css loader,然后是style loader
八、使用 babel-loader 转换 ES6 代码(上)
1、babel(1)、babel是一个转换编译器,它能将ES6转换成可以在浏览器中运行的代码(2)、安装babel终端目标文件夹输入:npm install --save-dev babel-loader babel-core(3)、loader:'babel-loader'可以正常运行,视频中的loader:'babel'不能正常运行。(4)、babel的loader是一个非常耗时的转换。改善之前的时间是8260ms
2、改善:(1)webpack 的api的configurationloaders的参数5个:test,exclude,include,loader,loaders(2)改善方法:exclude,include参数例如:exclude:'./node_modules/',//node_modules是已经引用过的,已经打包过的文件,其实这里对速度没有影响,这是告诉你如果是不相关的文件,可以用excludeinclude:'./src/',1)会报错:-configuration.module.loaders[0].exclude: The provided value "./node_modules/" is not an absolute path!2)报错的解决方法:    exclude:__dirname+'/node_modules/',//已经引用过的,已经打包过的文件    include:__dirname+'/src/',(3)这样初步改善后时间是1210ms
3、完整配置代码
// nodeJS原生的path方法,使用require引入const path = require('path');const htmlWebpackPlugin = require('html-webpack-plugin');module.exports = {    context: __dirname,    entry: {    main: './src/app.js'    },    output: {        path: path.resolve(__dirname, './dist'),        filename: 'js/[name].bundle.js',    },    module: {        rules: [            {                test: /\.js$/,                loader: 'babel-loader',                exclude: path.resolve(__dirname, '/node_modules/'),                include: path.resolve(__dirname, '/src/'),                options: {                    presets: ['env']                }            },            {                test: /\.css$/,                use: [                'style-loader',                {                  loader:'css-loader',                  options: {importLoaders:1}                },                 'postcss-loader'                ]            },            {                test: /\.less$/,                use: [                'style-loader',                {                  loader:'css-loader',                  options: {importLoaders:1}                },                 'postcss-loader',                 'less-loader'                ]            },            {                test: /\.scss$/,                use: [                'style-loader',                {                  loader:'css-loader',                  options: {importLoaders:1}                },                 'postcss-loader',                 'sass-loader'                ]            },            {                test: /\.html$/,                use: [                'html-loader'                ]            },            {                test: /\.tpl$/,                use: [                'ejs-loader'                ]            },            {              // 加入file-loader处理图片文件              test: /\.(png|jpg|jpeg|gif|svg)$/i,              use: [                {                  // loader: 'file-loader',                  loader: 'url-loader',                  options: {                    limit: 10000,                    name: 'assets/[name]-[hash:6].[ext]'                  }                }              ]            }        ]    },    plugins: [    new htmlWebpackPlugin({    filename: 'index.html',    template: 'index.html',    inject: 'body'        })    ]}

九、处理项目中的 css

1、安装style-loader和css-loader
终端目标文件输入:npm i style-loader css-loader --save-dev
2、webpack可以将任何资源视为一个模块。
3、这里将css引用进来,
(1)、app.js:用的是es6的import语法
(2)、webpack.config.js: module的loaders
4、postcss-loader
对css进行浏览器兼容性考虑时,可以用到这个loader
(1)、安装postcss-loader
终端目标文件输入:npm install postcss-loader --save-dev
(2)、是一个后处理器。
(3)、可以加浏览器的前缀
5、安装autoprefixer
终端目标文件输入:npm install autoprefixer --save-dev
(1)、loader处理方式是从右到左,即从数组的最后一项往前
(2)、webpack.config.js中,
视频中的配置现在的postcss已经不支持了,我的配置是

十、关于postcss-loader问题的有效解决方案:

1、在webpack.config.js同级目录下 创建 postcss.config.js
(1)postcss.config.js 代码如下
module.exports = {
    plugins:[
        require('autoprefixer')({ browsers: ["last 5 versions"]})
    ]
(2) webpack.config.js 代码如下

    module: {
        rules: [
            {
                test: /\.js$/,
                use: [
                    'babel-loader'
                ]
            },
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'postcss-loader'
                ]
            }
        ]
    }

2、webpack 2.4配置postcss-loader


module:{
rules:[
{
test:/\.js$/,
loader:'babel-loader',
exclude:path.resolve(__dirname+"/node_modules/"),
include:path.resolve(__dirname+"/src/"),
query:{
presets:'latest'
}
},
{
test:/\.css$/,
use:[
'style-loader',
{loader:'css-loader',options:{importLoaders:1}},
{
loader:'postcss-loader',
options:{
plugins:function(){
return [
require("autoprefixer")({browsers:['last 5 versions']})
]
}
}
}
]
}
]
}

十一、处理项目中的less与sass

1、less-loader
(1)、安装:
终端目标文件输入:npm i less-loader --save-dev
错误提示:npm WARN less-loader@4.0.3 requires a peer of less@^2.3.1 but none was installed.
说明less没有装
(2)、安装less
终端目标文件输入:npm i less --save-dev
2、less-loader
基本配置是 loader: ‘style-lander!css-loader!postcss-loader!less-loader’
3、sass-loader
(1)、安装
终端目标文件输入:npm i sass-loader --save-dev
出现错误提示:
npm WARN sass-loader@6.0.3 requires a peer of node-sass@^4.0.0 but none was installed.
说明需要安装node-sass,解决方法:
终端目标文件输入:npm i node-sass -g --save-dev

十二、处理模板

1、layer.html是模板文件
处理模板文件的做法:

(1)webpack将模板文件当做一个字符串进行处理。

(2)webpack将模板文件当成已经编译好的的模板的处理函数。
对js模板语法,模板引擎,模板的作用的认识和了解再来看这章会比较容易理解。
2、要支持html文件,安装html-loader
终端目标文件输入:npm install html-loader --save-dev
3、要支持.ejs文件或者是.tpl文件,安装ejs
终端目标文件输入:npm install ejs-loader --save-dev
layer.js载入ejs模板时,返回的是一个function,这时的import tpl from './layer.tpl';中的tpl代表的不再是字符串,表示的是一个已经编译过的函数
4、react——jsx
       vue——jsx

十三、处理图片及其他文件

##、添加图片
1、css中的背景图片。
(1)安装file-loader
终端目标文件输入:npm install file-loader --save-dev
2、模板文件layer.tpl直接引用图片。
(1)绝对路径:直接写绝对路径就行。
(2)相对路径:    <img src="${require('../../assets/bg.jpg')}"
3、最根部的文件index.html引用图片。
(1)绝对路径:直接写绝对路径就行。
(2)相对路径:file-loader
##、图片打包后的输出地址:
 1、       query:{
                  name:'assets/[name]-[hash:5].[ext]'
              }
2、安装url-loader
url-loader和file-loader相似,但是url-loader可以指定limit参数。
(1)终端目标文件输入:npm install url-loader --save-dev
url-loader可以处理文件或者图片,当文件/图片大小大于指定的limit,就会丢给filel-loader去处理,当小于设定的limit,就会转为base64编码,不再是一个url(不再是一个http请求),图片会被打包进html,css,js
(2)两种图片引用方式:①通过http请求load进来。浏览器会有缓存,比较适用于重复性较高的图片。②打包成base64。任何地方要用时,都会有base64编码存在那里,会造成代码的冗余,增加代码的体积。
##、压缩图片
1、安装image-webpack-loader
终端目标文件输入:npm install image-webpack-loader --save-dev
2、先压缩文件再传给url-loader判断。

原创粉丝点击