后端路由项目由 gulp 改为 webpack 的踩坑实录

本文分享了从使用Gulp构建前端项目的经验迁移到Webpack的过程,重点介绍了如何配置Webpack实现热重载、代理服务器及多模块打包等功能。

前言

公司有个后端路由的项目是用 gulp 作为前端自动化构建工具,最近学习了一下 webpack,深感其强大,一狠心将其改成了 webpack 构建,以下是踩坑实录。

gulp

先来说说原来的架构。

该项目是个 后端路由 的项目,我们以域名 www.abc.com 为例。假设有以下两个路由 www.abc.com/aboutwww.abc.com/join因为路由后端已经构建好,这个时候我们是可以打开这两个页面的。

后端模版为 php 的 twig(当然可以是其他任何模版),这两个路由分别对应两个 twig 模版(当然也可以是同一个模版)。因为网站首尾类似,所以我们有另外两个公用的 twig 模版分别是 header.twig 和 footer.twig,供其他单个页面的模版引用(twig 套 twig)。我们在 header.twig 以及 footer.twig 中分别引入 css 和 js 文件,大概这样:

// header.twig 中引入公共 css 和 模块需要的 css
<link rel="stylesheet" href="{{ cdn('/global/css/global.css') }}"/>
<link rel="stylesheet" href="{{ cdn('/' ~ moduleName ~ '/css/' ~ moduleName ~ '.css') }}"/>

// footer.twig 中引入模块需要的 js
<script crossorigin src="{{ cdn('/' ~ moduleName ~ '/script/' ~ pageName ~ '.js') }}"></script>

变量 moduleName 和 pageName 我们在具体的单个页面(比如 /about 路由对应的 about.twig 中)定义,这样就能引用到。

前端方面,用 sass 作为 css 预处理工具,requirejs 作为 js 模块化工具(r.js 打包),gulp 进行自动化构建,也就是说,最后打开的单个页面,除了公共部分的 js(至少得有 requirejs) 和 css(一些公共样式表,比如 bootstrap),还分别有一个页面独属的 js 和 css 文件。

大概就是这样,gulpfile 需要注意的几点有:

  • 我们用 browserSync 做前端 server 以及热重载工具,因为默认打开的 url 类似 localhost:3000,实际需要指向的是 www.abc.com,所以需要加入一个 proxy 参数,参数值 www.abc.com

    const browserSync  = require('browser-sync').create('proxy')
    
    gulp.task('bs', () => {
      return browserSync.init({
        proxy: "www.abc.com"
      });
    });
  • 监听 sass 文件以及 js 文件,如果文件改变,则编译(sass -> css,es6 -> es5)后重载页面(browserSync.reload),当然还需要监听模板页面(改变即重载)

  • 打包用的是 requirejs 在 node 端的工具 r.js

gulp 整体的使用流程还是很符合常人的思考方式的。

webpack

既然 gulp 那么好用,为何要学习 webpack?对于我而言,最难受的地方是 每引入一个模块都需要在 requirejs 中配置,这点不能忍,而且,rjs 打包实在太慢了,这点还没有与 webpack 的打包速度比较过。rjs 打包过程可以自己在 gulpfile 中配置,当页面模块多的时候我们可以分模块打包(打包就是自己写脚本,比较自由),webpack 貌似一运行 webpack
就默认全部打包了?这点还有待后续学习。

我们将 gulpfile 中需要做的几件事列出来,分别用 webpack 去实现,核心就是以下三件:

  • server,proxy,热重载
  • sass -> css,es6 -> es5
  • rjs 打包

第一件,webpack 可以直接用 webpack-dev-server 工具,关于 proxy,我们可以这样配置(需要做整站的 proxy):

devServer: {
  proxy: {
    "/": {
      target: "http://www.abc.com",
      changeOrigin: true
    }
  }
}

如果代码被 entry 中的配置文件所引用,并且改变,就会重载浏览器。js 文件没有问题,sass 可以被 js 文件引用,重载也没有问题,需要思考下模版文件的重载

第二件,我们可以配置 module,以下简单配置了 sass 和 css 的转换(还需要配置 babel, todo):

module: {
  rules: [
    {
      test: /\.css$/,
      use: [
        'style-loader',
        'css-loader'
      ]
    },
    {
      test: /\.scss$/,
      loader: 'style-loader!css-loader!sass-loader'
    }
  ]
}

这样我们就可以在 js 中引入 sass 和 css 文件了。

第三件,比较麻烦,webpack 默认单入口单出口,但是因为是后端路由的项目,不可能只打包生成一个 js 文件,需要配置多个入口多个出口,打包生成多个 js 文件。

我们来看下目录结构,原始 js 文件的地址是 src/xx/js/xx.js 形式,打包后的地址(也就是线上文件引用的地址)是 build/xx/js/xx.js(将 src 替换成 build)即可。

下面这样配置是可以的:

entry: {
  'course/js/apply.js': './src/course/js/apply.js',
  'course/js/content.js': './src/course/js/content.js'
  // others
},

output: {
  filename: "./build/[name]"
}

也就是 ./src/course/js/apply.js 打包后的地址是 ./build/[name],此时 name 值为 course/js/apply.js ,所以带入后实际就是 ./build/course/js/apply.js。一个个列出来显然麻烦(这不是跟 requirejs 一样了),写个脚本自动吧。

function getEntry() {
  // Walker options
  let files  = walkSync('src')

  let entry = {}

  files.forEach(item => {
    if (item.endsWith('.js')) {
      entry[item] = './src/' + item
    }
  })

  return entry
}

这里找了个 同步 获取文件夹下所有文件的包 walk-sync,生成入口参数。(我觉得这样写入口不优雅,暂时能用, todo)

ok,这样就大功告成了!每个页面引用单个 js,js 中可以引入 sass。

后语

用了一段时间的 gulp,gulp 本身是不提供模块化工具的,如果需要模块化,还是要引入类似 requirejs、seajs 一些的框架,或者使用 webpack 插件,但是 webpack 本身甚至提供了所有 gulp 能有的功能,关键还是自带模块化,何乐而不为呢?

我觉得我已经路转粉了。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值