logo头像
Snippet 博客主题

webpack & gulp制作脚手架

本文于1455天之前发表,文中内容可能已经过时。

前言

       前段时间学react、vue写了一些demo,为了方便调试每次都要复制一大推文件来支持热加载。然后文件就变得很多,最后连自己都搞不清楚每个demo的作用,基于此决定写一个脚手架。目前该项目已传至npm,地址为https://www.npmjs.com/package/npm-scaff

开发的脚手架要解决的问题

  • 支持多个框架
  • 配置文件可以通过命令自动生成,不需要每次手动复制
  • 配置文件只需要一份,可以调试多个页面
  • 可以进行热加载
  • 可以打包

如何解决以上问题

  • 其实不同框架本质都一样,都有一个入口文件,vue和react可以对这个文件进行进一步包装,比如vue,我就用在index.js里面render了App.vue这个单页面,这样开发的时候入口就是App.vue这个文件,react也是同理
  • 通过tj大神的commander可以用js去写一些命令
  • 只需要动态改变webpack中entry和output的路径就能调试多个页面
  • 可以通过webpack-dev-server这个插件
  • webpack只做2件事情,一个是模块的依赖,二是js的压缩,其他任务都交给gulp去做。

选择开发工具

  • commander tj大神开发的工具,可以用js去配置命令行参数
  • webpack webpack的优势是在分析各个模块之间的关系。
  • gulp gulp的优势就是任务流,速度快,任务可以自定义,结构清晰。光用webpack只能进行一些简单的配置以及模块的依赖,但是还有很多事情做不了,比如雪碧图的制作等,而且webpack的配置很复杂,api一直在变动,所以决定引入gulp,让webpack仅仅是作为gulp的一个子任务,用gulp去管理整体任务就会比较清晰了。

开发流程

  • 首先在本地创建一套基于webpack + gulp的前端开发脚手架。
  • 其次将这些文件全部放到包里面,一起上传到npm,这样用户执行npm install -g npm-scaff的时候就能把这些脚手架的文件都下载放到本地全局
  • 当用户执行pm init的时候其实就是把刚才安装在本地全局的那些脚手架文件从全局复制到新建的项目里面,同理pm add也是一样

webpack + gulp配置过程中的注意事项

  • 配置多个页面其实本质就是动态改变webpack里面entry、ouput的配置,可以通过首先通过readdirSync读取当前目录下面的文件,然后进行了一次for循环,再把每个值传递给那个webpack配置里面entry和output。
  • 要区分环境,可以通过webpack.DefinePlugin去定义一个全局变量,但是这边因为结合了gulp所以就不需要去特定定义这个变量了
  • open-browser-webpack-plugin 通过这个插件可以唤起浏览器
  • extract-text-webpack-plugin 这个插件在热更新的时候不能用,因为它会把css文件单独独立出来,这样修改css内容的时候就不会热更新了
  • 热更新的时候需要添加HotModuleReplacementPlugin这个插件
  • 热更新的时候需要在配置中添加 devtool:’eval-source-map’生成source map 方便调试。
  • webpack-dev-server其实就是起了一个express服务,文件入口路径在webpack-dev-server/client?http://localhost:8080,所以要把这个放到entry里面,热更新还需要把’webpack/hot/dev-server’也放进去entry里面,同时在output里面配置输出路径(publishPath),publishPath是提供给webpack-dev-server里面的publishPath。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    entry: {
    index: [
    path.resolve(__dirname, `../src/${dir}/index.js`),
    `webpack-dev-server/client?http://localhost:${port}`,
    'webpack/hot/dev-server'
    ]
    }
    output: {
    filename: "[name].js",
    path: path.resolve(__dirname, '../build/'),
    publicPath: `http://localhost:${port}/${dir}/`
    }
  • webpack-dev-server有2种方式进行配置,一个是命令行,直接在命令行后面添加–inline -hot,然后在配置里面配置devServer这个对象(和module,plugins同级),还有一种是通过node去配置,具体如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//webpackconfig为基础配置,devConfig(dir, port)为热更新配置
let optionConfig = merge(webpackconfig, devConfig(dir, port));
const myDevConfig = Object.create(optionConfig);
new webpackDevServer(webpack(myDevConfig), {
stats: {
colors: true
},
publicPath: devConfig(dir, port).output.publicPath,
historyApiFallback: true,
hot: true,
watchOptions: {
poll: true,
watch: true
},
watchContentBase: true
}).listen(port, "localhost", function(err) {
if(err) throw new gutil.PluginError("webpack-dev-server", err);
gutil.log("[webpack-dev-server]", `http://localhost:${port}/webpack-dev-server/index.html`);
});

结束

       使用文档已经写在npm里面的npm-scaff这个模块上了,可以自行阅览。目前暂不支持图片、字体以及mock数据,之后会补充,如有bug请及时联系我修复