怎样打造一个使人愉悦的前端开辟环境(二)

前情提纲

上一篇文章引见了现在前端比较盛行的种种编辑器,以及种种盛行的打包体式格局,末了给了一个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 剖析模块依靠的时刻,受影响的设置项。

  • extensions 决议了哪些文件后缀在援用的时刻能够省略点,Webpack协助你补全称号。

  • fallback 当webpack在 root(默许当前文件夹,设置时要绝对途径) 和 modulesDirectories(默许当前文件夹,相对途径)设置下面找不到相干modules,去哪一个文件夹下找modules

  • 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的东东。

    原文作者:乖小鬼YQ
    原文地址: https://segmentfault.com/a/1190000006201049
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞