您的位置:首页 > Web前端 > JavaScript

一步步深入学习webpack(入门困惑express和dev-server区别及分别使用dev-server和webpack-hot-middleware实现的热加载区别)

2018-03-26 19:59 1096 查看
最近需要对webpack详细学习后,给大家分享学习。于是不得不对每一个点进行学习,结果发现webpack涉及到的知识内容好多,自己学习也是一知半解,很多时候脑细胞都死得一片一片的。

注:本文是参考网上多方资料学习后记录的,如有雷同,请联系我。

学习资料:入门Webpack,看这篇就够了WebPack 简明学习教程Webpack飞行手册以及wepack官方文档

一、webpack是什么

Webpack是一款目前非常流行的前端模块打包工具,可将项目中所加载的模块进行打包,以及将一些浏览器不支持的语言进行转换。

两个最核心原理:一切皆模块、按需加载。

打包原理:先找到入口文件,递归探索出所有依赖的模块,最后利用Loader进行不同文件的类型的处理,最终打包为一个文件。

另外,webpack遵循Common.js规范,也就是项目出现的require()方式的加载模块,以及每个模块的自由变量exports(是对外输出API的唯一途径)等。

注意:Common.js是模块化开发的标准,此外还有AMD(RequireJS在推广过程中对模块定义提出的概念)和CMD(SeaJS在推广过程中对模块定义提出的概念)。其中,AMD是预加载,遵循异步模块定义(^ ^ps:这个还没懂)在使用它时,它会尝试第三方类库修改自身来支持 RequireJS,且插件类型比较单一;而后者是并行加载js文件,可以同一时间解析多个文件,但这时加载顺序不一定,插件类型比较丰富。

补充:在过程中有接触到SASS(css语法超级),后来又有SCSS是SASS的新语法。SASS的基本用法:

(1)允许使用变量,所有变量以开头,eg:开头,eg:blue:#1875e7;

(2)变量需要嵌在字符串中,必须写在#{}中;

(3)有计算功能,可以在代码中使用算式;

(4)嵌套;

(5)注释风格/* / 和 /!重要注释*/

webpack使用可以使用不同的Loader,调用外部的脚本或者工具,实现对不同格式的文件处理。提供两个工具处理样式表:

(1)css-loader:使你可以使用类似@import和url()实现require()加载;

(2)style-loader:将计算后的样式假如页面,二者组合在一起使用可以将样式嵌入webpack打包后的JS文件中;

Babel则是编译JavaScript的平台,让我们可以使用新的JavaScript标准(如:ES7、ES6),也可使用基于javaScript的扩展语言,如React的JSX。

二、安装步骤

1.新建项目文件,且在终端中进入该目录;

2.全局安装:npm install –g webpack

3.本地安装:npm install –save-dev webpack

4.初始化: npm init

5.安装webpack服务器 npm install –save-dev webpack-dev-server

三、使用



在按第二部分安装好后,我们就可以对webpack进行使用了,使用方法可以通过终端命令或者是配置文件来进行。一般采用后者,配置好后,就可以直接在teminal中使用webpack系列命令,前者易出错且难一点。因此,使用webpack进行打包,一般我们需要在项目中新建一个webpack.config.js配置文件,基本结构如上图所示,作用就是告诉webpack需要做些什么。

(1)entry:webpack工作开始的地方,找到所依赖的模块,按顺序利用Loader处理

三种数据类型:字符串、数组(数组中每一项都会被打包,形成互不依赖的文件)、对象(对象中每一个属性都会被打包,形成互不依赖的文件)

(2)output:打包后文件的具体配置,打包文件所在路径及打包后文件的名字,常用的属性配置如下:

path:打包后文件所在路径;

filename:打包后文件的名字(四种常见写法:自定义、[name].js即入口的文件名、[hash].js打包后的hash值、[chunkhash]该块打包后的hash值);

publicPath:上线时的公共路径,主要应用于线上(eg:如果是设置了为static,则线上运行时,http://localhost:port/static/入口路径);

chunkFilename:’js/[name].js’:按需加载模块时输出的文件名称;

(3)module——Loader: 将不同格式的模块转换为浏览器统一可识别的,利用test进行正则匹配。两种写法:loaders:[{loader:’style-loader’},{loader:’ ‘},{loader:’ ‘}]或者是使用!号拼接的方法:loader:”loader1!loader2!…”

(4)plugins:插件用于扩展更多的功能需求;

使用较多的是html-webpack-plugin插件,用于生成HTML(如果需要多页面,有几个页面就需要几个htmlWebpackPlugin);

还有webpack-dev-middleware中间件,好处就是不会向硬盘写文件,而在内存中,文件改变时保存后,只要直接刷新浏览器就可以看到最新结果;

如果想要不用刷新就能检测到变化自动更新,则需要webpack-hot-middleware,进行页面的热重载
4000
的;

(5)devtools:可设置生成不同的sourcemap类型,方便调试定位;

(5)devServer:本地服务器,可以监听代码修改,并自动刷新显示修改后的结果;

(6)resolve: 设置模块被解析的一些约定(如引入方式等,extention:[“.js”,”.html”,”css”,…],这表明我们在require加载对应后缀名的文件时,可以省略后缀名);

四、手把手跟着前辈脚步走

正是通过对这篇文章——一步步构造自己的vue2.0+webpack环境的反复实践,终于对webpack更熟悉了解了。然后由于这篇文章是博主16年底写的,如今的新版运行,在写法和使用上可能又很大的差别,因此,虽然博主手把手地写下了这篇博客,我也踩了大半天的坑。

1.简要记录下自己修改的几个地方:

(1)安装未安装的依赖;

(2)修改现在的loader写法,module/rules:[];

(3)且在书写匹配不同的loader时,不能省略后缀eg:vue-loader;

(4)去掉没有的Fevlist对象属性;

(5)另外还需要新建出口文件output;

2.途中的小疑问

(1)利用node.js中的express服务器和webpack中dev server实现开启服务有什么不同吗?

经查询,dev server也是一个轻量级的node.js express服务器,实际上相当于是一个封装好的express的http服务器+调用webpack-dev-middleware。

例如一般可能会有如下的配置,当服务器启动时,启动命令是:webpack-dev-server –config wepack.config.js(配置文件路径),在解析模板列表前会有如图所示的提示信息。

devServer: {
historyApiFallback: true, // 404的页面会自动跳转到/页面
inline: true, // 文件改变自动刷新页面
port: 3800, // 服务器端口
},




而我们可以使用express服务器进行更多的扩展,结合使用其他的中间件来响应http请求及其他的功能,扩展性更好,较为灵活。这种方式下的编译命令一般是:node build/dev-server.js(配置文件路径)。

补充:中间件,是一个函数,用于访问请求对象、响应对象和web应用中处于请求-响应循环流程中的中间件。它的功能包括:执行任何代码、修改请求和响应对象、终结请求-响应循环和调用堆栈中的下一个中间件。

(2)热加载/热更新,使用devServer和使用webpack-dev-middleware+webpack-hot-middleware区别

devServer正如(1)中一样,express+webpack-dev-middleware,源文件改动后,会进行实时编译,再用webpack-dev-middleware将编译后文件输出到内存中.

而后面两种,如果单用前面一种需要手动刷新浏览器,加上webpack-hot-middleware才可以实现浏览器的无刷新更新,也就是HMR,不需要刷新整个页面。热加载却要刷新整个页面。

(⊙o⊙)我天我在说啥,我也搞不清楚了,上面两个问题仅限于当下的理解,避免不了有错误之处。

(3)path.resolve( ),到底是怎么进行路径转换的?

path.resolve('/foo','/bar','baz');     // /bar/baz
path.resolve('/foo/bar','./baz');      // /foo/bar/baz
path.resolve('/foo/bar','/tmp/file/'); // /tmp/file


查询了官方API,写得比较隐晦,只写了结果没有具体原理,还有看到了这篇文章《JavaScript 标准参考教程(alpha)》,by 阮一峰,其中列了一个小实例来说明。

path.resolve('foo/bar', '/tmp/file/', '..', 'a/../subfile')


其执行效果类似于:

cd foo/bar
cd tmp/file
cd ..
cd a/../subfile
pwd       //展示整个路径名


在代码里验证打印输出为: /tmp/subfile。最开始进入foo/bar路径目录下,然后又进入tmp/file目录下(末尾的/自动隐藏),又进入当前路径的上层路径即tmp下,接着就是又进入当前目录下的a即tmp/a,然后又是上级tmp/,最后就是subfile,因此最终路径为tmp/subfile。

即resolve进行路径转换时,同级目录参数,前面的直接被覆盖!正如例子中(1),bar覆盖了foo.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  js