如何打造一个令人愉悦的前端开发环境(二)

前情提要

上一篇文章介绍了目前前端比较流行的各种编辑器,以及各种流行的打包方式,最后给了一个Gulp的例子,这个例子还是14年的时候写的,还有一些可以优化的空间,就不讨论了,这篇文章主要讲目前火热的打包构建方式--Webpack的使用方式。

主菜--没有开胃汤

其实Webpack的入门指导文章非常多,配置方式也各有各样,这里我推荐题叶大神的入门级指南--Webpack 入门指迷,如果不知道Webpack是什么或者不是很清楚各项配置含义的开发者,可以看此文章扫扫盲。毕竟我这篇文章并不是特别基础。

一、base.js

var path = require('path')var baseConfig = {    resolve: {        extensions: ['', '.js'],        fallback: [path.join(__dirname, '../node_modules')],        alias: {            'src': path.resolve(__dirname, '../src'),            'assets': path.resolve(__dirname, '../src/assets'),            'components': path.resolve(__dirname, '../src/components')        }    },    module: {        loaders: [{            test: /\.js$/,            loader: 'babel',            exclude: /node_modules/        }, {            test: /\.(png|jpe?g|gif|svg|woff2?|eot|ttf|otf)(\?.*)?$/,            loader: 'url?limit=8192&context=client&name=[path][name].[hash:7].[ext]'        },        {            test: /\.css$/,            loader: 'style!css!autoprefixer',        },        {            test: /\.scss$/,            loader: 'style!css!autoprefixer!sass'        }]    }};module.exports = baseConfig;

解读下这个基本配置:

1、resolve 解析模块依赖的时候,受影响的配置项。

  1. extensions 决定了哪些文件后缀在引用的时候可以省略点,Webpack帮助你补全名称。

  2. fallback 当webpack在 root(默认当前文件夹,配置时要绝对路径) 和 modulesDirectories(默认当前文件夹,相对路径)配置下面找不到相关modules,去哪个文件夹下找modules

  3. alias 这个大家应该比较熟悉,requirejs之类的都有,就是别名,帮助你快速指向文件路径,少写不少代码,而且不用关心层级关系,需要注意的是:在scss之类的css预编译中引用要加上~,以便于让loader识别是别名引用路径。

2、module 解析不同文件使用哪些loader,这个比较简单,很多文章都有,就不多说了,注意的是,这里的scss可以换成你自己的预编译器,例如:sass、less、stylus等,或者直接用postcss都行,当然还可以用一种通用方法,后面补上。

二、开发环境配置--config

var webpack = require('webpack');var path = require('path')var merge = require('webpack-merge')var baseConfig = require('./webpack.base')var getEntries = require('./getEntries')var hotMiddlewareScript = 'webpack-hot-middleware/client?reload=true';var assetsInsert = require('./assetsInsert')module.exports = merge(baseConfig, {  entry: getEntries(hotMiddlewareScript),  devtool: '# eval-source-map',  output: {    filename: './[name].[hash].js',    path: path.resolve('./dist'),    publicPath:'./dist'  },  plugins: [    new webpack.DefinePlugin({      'process.env': {        NODE_ENV: '"development"'      }    }),    new webpack.optimize.OccurenceOrderPlugin(),    new webpack.HotModuleReplacementPlugin(),    new webpack.NoErrorsPlugin(),    new assetsInsert()  ]})

说说这个配置中的一些难点:

1、getEntries 是用来配置入口文件,一般很多人是自己手写,或者SPA页面,只有一个入口, 很容易就写出来,但是公司中,很多情况,是需要多入口,也就是多路由的Url,这个时候入口的配置就比较麻烦,我这里是放单独一个文件里面配置,我们公司是靠规定来执行,也就是一个文件夹所有的main.js都认为是入口文件,其他都忽略。

function getEntry(hotMiddlewareScript) {    var pattern = paths.dev.js + 'project/ /main.js';    var array = glob.sync(pattern);    var newObj = {};    array.map(function(el){        var reg = new RegExp('project/(.*)/main.js','g');        reg.test(el);        if (hotMiddlewareScript) {            newObj[RegExp.$1] = [el, hotMiddlewareScript];        } else {            newObj[RegExp.$1] = el;        }    });    return newObj;}

2、assetsInsert 是用来做模板替换的,一个小插件把template里面的值替换成打包后的css或者js。

三、打包环境配置--production

var webpack = require('webpack');var path = require('path')var merge = require('webpack-merge')var baseConfig = require('./webpack.base')var getEntries = require('./getEntries')var ExtractTextPlugin = require('extract-text-webpack-plugin');var assetsInsert = require('./assetsInsert')var productionConf = merge(baseConfig, {    entry: getEntries(),    output: {        filename: './[name].[hash].js',        path: path.resolve('./public/dist'),        publicPath: './'    },    plugins: [        new webpack.DefinePlugin({            'process.env': {                NODE_ENV: '"production"'            }        }),        new ExtractTextPlugin('./[name].[hash].css', {            allChunks: true        }),        new webpack.optimize.UglifyJsPlugin({            compress: {                warnings: false            }        }),        new webpack.optimize.OccurenceOrderPlugin(),        new assetsInsert()    ]})productionConf.module.loaders = [             {                test: /\.js$/,                loader: 'babel',                exclude: /node_modules/            }, {                test: /\.(png|jpe?g|gif|svg|woff2?|eot|ttf|otf)(\?.*)?$/,                loader: 'url?limit=8192&context=client&name=[path][name].[hash:7].[ext]'            },            {                test: /\.css$/,                loader: ExtractTextPlugin.extract('style', 'css'),            },            {                test: /\.scss$/,                loader: ExtractTextPlugin.extract('style', 'css!sass')            }]module.exports = productionConf

基本跟开发的差不多,差别在于:
1、使用ExtractTextPlugin 来打包css,所以要干掉原来base的loaders,重新写了一个,在最下面。

2、UglifyJsPlugin 给js压缩代码。其他没有什么好解释的了,一样的。

四、构建命令

require('shelljs/global')env.NODE_ENV = 'production'var ora = require('ora')var webpack = require('webpack')var webpackConfig = require('./webpack.production.config')var spinner = ora('building for production...')spinner.start()var staticPath = __dirname + '/../public/dist/'rm('-rf', staticPath)mkdir('-p', staticPath)webpack(webpackConfig, function (err, stats) {  spinner.stop()  if (err) throw err  process.stdout.write(stats.toString({    colors: true,    modules: false,    children: false,    chunks: false,    chunkModules: false  }) + '\n')})

写一个build.js,然后在package.json里面添加 script 参数

"build": "node build.js"//这里记得写自己build.js路径

甜点(马卡龙)--有点腻

上面的配置是可以更改的,例如你在loaders 里面加上

{  test: /\.vue$/,  loader: 'vue'}

就可以变成支持.vue文件的vuejs打包构建,同理,修改下支持jsx,和添加一些reactjs的module,就可以用来跑Reactjs的东西。

还有可以随意更改Css预编译器的类型,用你自己喜欢就行,或者跟我们前面提到的方法,把所有类型都配置上,

var path = require('path')var config = require('../config')var ExtractTextPlugin = require('extract-text-webpack-plugin')exports.assetsPath = function (_path) {  return path.posix.join(config.build.assetsSubDirectory, _path)}exports.cssLoaders = function (options) {  options = options || {}  // generate loader string to be used with extract text plugin  function generateLoaders (loaders) {    var sourceLoader = loaders.map(function (loader) {      var extraParamChar      if (/\?/.test(loader)) {        loader = loader.replace(/\?/, '-loader?')        extraParamChar = '&'      } else {        loader = loader + '-loader'        extraParamChar = '?'      }      return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '')    }).join('!')    if (options.extract) {      return ExtractTextPlugin.extract('vue-style-loader', sourceLoader)    } else {      return ['vue-style-loader', sourceLoader].join('!')    }  }  // http://vuejs.github.io/vue-loader/configurations/extract-css.html  return {    css: generateLoaders(['css']),    postcss: generateLoaders(['css']),    less: generateLoaders(['css', 'less']),    sass: generateLoaders(['css', 'sass?indentedSyntax']),    scss: generateLoaders(['css', 'sass']),    stylus: generateLoaders(['css', 'stylus']),    styl: generateLoaders(['css', 'stylus'])  }}// Generate loaders for standalone style files (outside of .vue)exports.styleLoaders = function (options) {  var output = []  var loaders = exports.cssLoaders(options)  for (var extension in loaders) {    var loader = loaders[extension]    output.push({      test: new RegExp('\\.' + extension + '$'),      loader: loader    })  }  return output}

这就是把所有的css预编译的都加到配置里面了。

总结下--买单啦

Webpack多种多样,就算一个loaders都有好几种不同的配置,让人很是头疼,最关键的是很多插件自己的文档也不清不楚,弄得大家都很迷茫,我的经验就是多试多测,自己多写一写,看命令行打印的错误,去找原因,不要一看到报错就慌了,很多新手最容易犯错就是一看到报错就怀疑人生了,一定要看报错记录,一般都有提示,按照提示去解决相应问题就好啦。

下一章我们讲Nodejs的东东。

关键字:JavaScript, webpack, node.js, html

版权声明

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部