*本文需知,渣小白,可能会有很多错误,希望指出,亲身踩坑经历总结
*本文内容,关于前端自动化的基本理解以及从零开始构建一个自动化项目
学习前端也半年有余吧,在网上的前端学习初级教程中,是学习html/css/js的基本使用,然后进阶开始学习各种打包工具啊什么的,感觉这个过程非常困难,因为突然很多的概念,感觉有种很乱很乱的理不清的感觉。(笑)这篇文章就是我的理解吧。(可能有很多错误,非常希望有人能指出QUQ(再次强调
前端初级学习
最开始学习前端的时候,其目录结构是这样的↓↓↓
|-------index.html
|-------css
|------index.css
|------xxx.css
|-------js
|------index.js
|------xxx.js
复制代码
嗯,没什么毛病。我也这么一直度过了半年
其实这对前端的初学者来说感觉没毛病,因为一开始做小demo的话,这样也的确能够搞定。
前端自动化工具
在上面的一个阶段呢,写js基本上就是一个文件从头写到尾,css文件也是,然后要共用的部分甚至不是抽出一个单独的部分而是直接复制粘贴。这样就有很多的问题,写码一时爽,维护。。。。算了这种等级的demo根本不需要维护(笑)
但是当做的网站越来越复杂的时候,这样的结构来说过于简单,不利于大型项目的模块开发,以及后续的维护工作,在较大的项目中,尤其是多人的情况下,如何组织多个模块,这就成了一个问题(在初级学习的时候甚至连import都不需要,当然不需要的什么组织啊结果啊之类的 ~ ),怎么说呢,当有需求的时候就会去寻找新的工具,来满足需求。
所以,当当当~这种情况下就需要gulp,grunt,webpack 等等自动化构建工具,这类工具可以管理项目的各类文件之间的关系,解决之间项目引用的问题。当然也不止这些,还有上线的时候做的一些压缩,uglyfy,然后各种吧!总之这些工具,基本上是可以解决从开发到上线等等一系列问题。
这个时候目录结构就变成了这样 ↓↓↓
|-------dist //构建完了之后用来上线的目录
|-------js
|------index.bundle.js
|-------images
|------xxx.jpg
|-------src //生产目录
|-------script
|-------style
|-------webpack.config.js
|-------package.json
复制代码
安装以及核心概念
-
首先初始化文件夹
npm init 复制代码
然后就会有这么多东西要填,分别是填对应这个工程的名字(package name),版本(version),描述(description),入口文件(entry point),test命令(test command),关键字(keywords),然后作者(author),最后是模块协议(license)
这一步呢,就是初始化文件夹,当然像我这样全部默认的话完全可以
npm init -y
复制代码
这样可以少敲不少回车
这里很多都可以从字面上理解,主要要解释的
-
这样会生成一个package.json文件
这个是最最最最最最重要的一个文件之一,这个是一个项目的配!置!文件,好了知道配置文件就知道重要性了(笑)
-
main
这个是这个项目的默认入口文件
-
script
这个是用于快捷输入命令行的,比如说在构建的时候我们经常会带上一大堆参数,我们可以在script里面写上,然后下次直接npm run + 你给这条命令取的名字 就好啦~
-
devDependencies 和 dependencies
这两个属性呢,在初始化的时候还没使用到,这个在之后安装模块的时候,是使用到这个的
其实最直观的差别就是
npm install xxxx --save-dev npm install xxxx --save 复制代码
参数不一样
dependencies 呢就是程序运行的时候所必须的模块(emmmm 类似引用jQuery那种?)
devDependencies 呢就是程序在开发的时候用到的一些辅助工具啊,比如babel,webpack之类的,这种只要在开发的时候用,发布的时候并不需要的发布的就放在jQuery中
-
大致要用到的就这些,其他用到的后续会补充,以及想要详细了解,传送门 ↓
docs.npmjs.com/files/packa…
-
这里选择webpack啦2333
-
既然用webpack,那么第一步就是安装webpack啦
npm install webpack -g 复制代码
咦,为什么是 -g ?webpack 用之前要全局安装一下,不然之后运行webpack命令的时候会报错= =!
安装之后在终端输入 webpack 还是会报错,阅读报错信息他就会提示你安装一个关于 webpack的命令的包,所以呢可以直接根据提示安装或者直接
npm install webpack-cli -g 复制代码
-
通过第一步,就有webpack这个工具在,那么怎么使用呢?
当然,还是主要通过配置文件——webpack.config.js,不知道这个会不会自己生成,不会的话那就自己创建一个,都一样的啦23333
webpack.config.js 这个文件,看后缀名就知道是个js文件(废话
它还是遵守commonJs的规范,所以,他的主要结构还是
module.exports = { //...各种配置 } 复制代码
-
4个核心概念
-
entry
简单来说就是打包的时候的文件入口
-
output
简单来说就是打包的时候的文件出口
-
loader
这个概念没有前面两个那么明显,查看webpack文档,它是这么介绍loader的:→传送门
翻译一下就是:
webpack只能解析js文件,通过loaders , webpack可以打包其他文件的,然后将它转化成module然后他就可以 被你的应用使用了。
并且注意可以处理任何类型(类似.css)文件是webpack的一个特有能力,可能不支持于其他的工具,我们认为一个语言的拓展性是非常必要的,这样可以方便开发者创建更加准确的依赖图
loader含有两个的属性需要在webpack中配置:
- test 匹配规则,匹配哪种类型的文件
- use 匹配成功之后用哪种的loader处理
-
plugin
plugin,这个还是看文档吧,官方文档其实也说的很清楚了→传送门
翻译一下呢,就是loader被用来转化各种类型文件,plugin则可以完成更大范围的任务,就像打包的优化,资源管理和更改环境变量
然后就是怎么使用plugin,你需要require它们然后将它加入plugins的数组里面,大多数plugin都是可以通过选项配置的。你可以使用一个plugin在同一个配置文件中多次使用,这时你需要使用new操作符来实例化它。
-
具体配置
核心概念介绍完开始,那么就可以开始配置了
-
既然要开始打包,就要设置入口文件和出口文件
{ entry: "./src/index.js", output:{ path:path.resolve(__dirname, 'dist'), filename: "js/[name].bundle.js" }, } 复制代码
-
出口和入口可以凭借英文很直观的了解~
-
这个只是最基本的写法啦23333
-
当然还有多种写法
-
关于entry
刚刚上面的结构其实是这样的
这个是一个文件入口对不对,那么我们想要多个文件入口怎么办呢,比如从一个文件进入,并不能将我所需要的文件全部打包进来,就像下图,它存在平行关系,这种时候要怎么办呢,
来,继续打开官方文档→传送门
咦,single entry?单入口?好像跟我们想的不一样?
看图片最下方的蓝色小字,当你给entry传入一个数组会发生什么呢?通过传入一个数组的到 entry创建多入口文件,这当你想在给多个独立的(就是没有相互依赖关系的)文件打包到同一个chunk下非常有用。
所以想实现多入口文件的话,只要传入一个数组就行啦!上面那张图就可以按照以下的写法写就行了。
{ entry: ["./src/index.js","./src/c.js"], output:{ path:path.resolve(__dirname, 'dist'), filename: "js/[name].bundle.js" }, } 复制代码
嗯,刚刚又多了一个新名词,chunk。
什么是chunk呢,我的个人理解就是,webpack给每个依赖关系划分为一个chunk
刚刚之前那个数组就是一个chunk,我们这种写法的就不明显了,我们换个写法
{ entry: { main:["./src/index.js","./src/c.js"], d:["./src/d.js"] }, output:{ path:path.resolve(__dirname, 'dist'), filename: "js/[name].bundle.js" }, } 复制代码
这样写就明显多了,刚刚那个数组其实就是对应了一个叫做main的chunk,并且可以有多对chunk,chunk有什么用呢?这个在定义output就有用啦!
-
-
output
首先查看官方文档→传送门
filename是对应的输出文件的名字,如果就像上面的,官方文档的例子是一直定义成了"bundle.js",我前面的例子使用到了一个"[name]"关键字,这个呢是一个关键字吧,就是对应的chunk的名字,然后这样就可以直接生成对应的bundle.js然后其实还有一些其他的的关键字,比较常用的[chunkhash ],[hash]
在官方文档上没有找到这个两个词的解释,在这里找到一个两年前的官方解释。感觉这东西也没什么道理会变就引进来了
[hash]就是这次编译的hash,[chunkhash]就是这个chunk的hash
这么理解吧,[hash]就是只要编译了,那么一定就会变(因为是和编译挂钩的),chunkhash呢是看这次编译之后这个chunk生成的文件内容变化了没有,变了的话[chunkhash]就会变
-
出入口讲完了,现在该loader了
官方文档走一波→传送门
前面一大段是讲loader的作用的,我们看完之后可以开始看样例:
第一步当然是安装loader啦~
就像前面entry,output,loader对应的是module哟,
然后就有rules来匹配,这个照着官方文档来就行
就像前面介绍的时候一样,每个rule下面的要有test和use
其实看着官方文档和前面的介绍就很简单啦2333
然而并不是只有这么简单{ test:/\.css$/, loader:'style-loader!css-loader' } 复制代码
咦好像和上面的有一点不一样,
来,我们首先来理解一下这两个loader是什么鬼,第一个cssloader第二个是处理styleloader(解析是从后往左)styleloader是从可以讲css样式插入到html文档和head标签里面的,这就是两个loader串在一起
当然还可以三个
{ test:/\.css$/, loader:'style-loader!css-loader?importLoaders=1!postcss-loader' } 复制代码
咦道理我都懂,再加一个参数加一个!+新loader不就好了吗?importLoaders=1这个又是什么
这里呢我们用到postcss-loader的一个插件叫做autoprefixer ,给自动增加浏览器前缀,其实不加?importLoaders=1也是可以用的,但是还是会有一个问题,当在css文件中使用@import 文件这时候import进来的文件就不会加浏览器前缀,这个时候就通过传参(类似url中的get传参)importLoaders参数呢就是用来指定css中import进来的资源的通过几个loader,因为后面只有postcssloader所以importLoaders=1
关于postcss-loader的配置我就不多说了,具体配置方法可以查看官方文档→传送门
其他的也都大同小异,我就直接放我之前配置的
module:{ rules:[ { test: /\.js$/, exclude: path.resolve(__dirname, "node_modules"), include: path.resolve(__dirname,"src"), loader: "babel-loader", query:{ //babel参数配置 "presets": ["env","react"] } }, { test:/\.css$/, loader:'style-loader!css-loader?importLoaders=1!postcss-loader' }, { test:/\.scss$/, loader: 'style-loader!css-loader!postcss-loader!sass-loader' }, { test:/\.html$/, loader:'html-loader' }, { test:/\.(jpg|png|gif|svg|mp3|ico)$/i, loader:'url-loader', query:{ limit:20000, name:'[name]-[hash:5].[ext]', outputPath: 'images/' } } ] }, 复制代码
其中比较特殊的就是
-
babel-loader
这个loader的配置方法可以直接http://babeljs.io/setup然后选择webpack就有详细的教程~
-
sass-loader
sass-loader还依赖与一个node-sass,下个包会被墙,可以尝试淘宝源
npm i node-sass --sass_binary_site=https://npm.taobao.org/mirrors/node-sass/ 复制代码
-
url-loader/file-loader
这两个是一起使用的,
file-loader:返回的是图片的public URL。
url-loader:与file-loader不同,url-loader可以在图片大小小于设定的limit的时候返回的是一个DataURL(base64码),大于limit时会调用file-loader对图片进行处理。
-
-
最后就是plugin了,这个我用的也不多我就用了一个html-webpack-plugin orz
那,plugin要怎么用呢,我就拿html-webpack-plugin举例吧(放弃webpack官方文档
那。我们就打开html-webpack-plugin的文档→传送门
第一步当然是安装
npm i --save-dev html-webpack-plugin 复制代码
就像前面介绍的,webpack中怎么使用plugin,require,然后在plugin数组中添加,所以看文档的时候也可用知道
打包结果
就这么简单((((
显然不可能为了应对多种状况,plugin当然是可以配置的
比如html-webpack-plugin
plugins:[ new htmlwebpackplugin({ filename: 'index.html', template: './src/index.html', chunks: ['index'], favicon:'./src/component/20180806050252871.ico', }), ], 复制代码
在实例化plugin的时候可以传入一个对象,然后对其进行配置
filename是生成的html名字,template是模板html的路径
chunks,这个就是生成html中引入的js的chunk的名字,还记得
大明湖畔之前提到的chunk的作用吗,你看这里就可以很好的体现chunk的作用了,favicon是icon的配置,还有更多配置参数可以从上面我给的官方文档自己查阅
小结
终于写完了(╯‵□′)╯︵┻━┻
一写写了这么多
嗯,而且还只是个初步配置,其实我后面配置的不止这些,还是那句话吧,有需求时才会去寻求工具去解决。这个过程可能没有那么简单XDDD但是解决了真的很方便。
最后多查文档吧!文档大多数都给出了很多的解决方案,顺带webpack的文档我看的有种云里雾里的感觉。。。。