一、webpack可以实现的功能
可以打包 AMD、CMD、Common、css\、coffee、json、Image 等均可打包,也可以打包自定义后缀的文件,如:.vue、.jsx 等,都可以通过loaders加载器进行处理打包。
目前webpack+react+es6 的组合非常常见。
特性:
二、webpack的目标(1)、将js、css等文件视为一个模块,将外部或者第三方文件也视为一个模块 (2)、实现按需加载,是浏览器能够在最短时间打开项目 (3)、适合大型项目操作
(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 //下载webpacknpm init // 在项目中引导创建一个package.json文件 安装包的信息可保持到项目的package.json文件中,以便后续的其它的项目开发或者他人合作使用,也说package.json在项目中是必不可少的。(5)、style.loader!css.loader 意思是!前模块依赖!后模块,就是style依赖css(6)、我想看到打包过程,可以使用--progress, 在此我们可以看到一个百分比读条2、如果想用不同的模版生成不同的html文件,只用在plugins里添加各种htmlWebpackPlugin的实例就好了。webpack hello.js hello.bundle.js --module-bind "css=style-loader!css-loader" -progress(7)、每一次在命令行输一次命令行命令,十分的繁琐,可以使用--watch使它自动更新,自动打包。(aSuncat: css-loader后面不要加!,mac下是单引号'',windows是双引号"")1、多页面如何引用属于自己的js文件,可以借助htmlwebpackplugin配置chunkswebpack 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其他参数:六、自动化生成项目中的html页面(三)--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需要先引入pathmodule.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-dev 2. 在配置文件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 run 5. 生成的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>
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为false 7、小结 (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)、直接配置配置文件 loaders test:对资源的正则匹配,如果匹配到Loader,就会对其进行处理。 (3)、直接使用cli webpack --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的configuration loaders的参数5个:test,exclude,include,loader,loaders (2)改善方法:exclude,include参数 例如:exclude:'./node_modules/',//node_modules是已经引用过的,已经打包过的文件,其实这里对速度没有影响,这是告诉你如果是不相关的文件,可以用exclude include:'./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判断。