webpack使用体验

node知识

path.resolve

path.resolve(from[...pathname], to)将参数to位置的字符解析到一个绝对路径里。
__dirname 当前文件目录绝对路径
__filename 当前文件全路径
demo示例:(当前目录: D:\www\programs\react-prod\config)

// 相对路径根据当前位置绝对路径解析
// ../匹配上一层
// ./ 或者 没有./匹配当前路径
// D:\www\programs\react-prod\config\dist
path.resolve('./dist')
// D:\www\programs\react-prod\dist
path.resolve('../dist')
// D:\www\programs\react-prod\config\www\dist
path.resolve('www/demo', '../dist')
// D:\dist绝对路径直接返回
path.resolve('/dist')

// 如果只传递一个参数,那么相对路径将基于当前命令的执行路径
输出

console.log(path.resolve('./dist'))
console.log(path.resolve(__dirname, './dist'))

当在D:\www\programs\react-prod路径下执行时,分别返回

D:\www\programs\react-prod\dist
D:\www\programs\react-prod\script\dist

当在D:\www\programs\react-prod\script路径下执行时,分别返回

D:\\www\\programs\\react-prod\\script\\dist
D:\\www\\programs\\react-prod\\script\\dist

所以为了表现一致,path里面解析绝对路径,需要加上__dirname


webpack知识

context
配置基础目录,使config中的相对路径基于这个目录,这样,不管webpack配置文件放在哪里,我们在文件内部引用外部文件时,都可以根据一个相同的基础目录解析文件,只需修改config.context一个地方就可以了。

entry入口

用法:

  1. 单入口: entry: string|Array<string>,传入数组会将数组中的文件作为统一一个入口一起打包成一个文件
  2. 多入口: 用法:entry: {[entryChunkName: string]: string|Array<string>}根据入口打包成多个js文件

output输出

在 webpack 中配置 output 属性的最低要求是,将它的值设置为一个对象,包括以下两点:

  1. filename 用于输出文件的文件名。
  2. 目标输出目录 path 的绝对路径。

常用loaders

1.css-loader

css加载器 css-loader, style-loader
css-loader 解释(interpret) @import 和 url() ,会 import/require() 后再解析(resolve)它们
style-loader用来将解析出来的css内容添加到页面的style标签里面。但是一般情况下我们都会将css样式与js文件分离,这样可以有效减小代码体积。2.66kb -> 816bytes+27bytes
css-loader+style-loader一般需要结合两个plugin一起使用,分别用于将css分离和压缩

// 用于提取css的plugin
const ExtractTextPlugin = require('extract-text-webpack-plugin')
// 用于压缩css的plugin
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
...
// module.rules[num]
{
    test: /\.css$/,
    // 它会将所有的入口chunk(entry chunks)中引用的 *.css,
    // 移动到独立分离的 CSS 文件
    // css bundle 与 js bundle 并行加载,加快页面初始化
    use: ExtractTextPlugin.extract({
      fallback: 'style-loader',
      use: 'css-loader'
    })
    // style-loader用来将css-loader解析(import,url()等)出来的css
    // 插入到页面的<style>标签里面,没有则无法正常引用
    // 使用etp时则作为降级处理
    // use: ['style-loader', 'css-loader']
}
...
plugins: [
    // name为入口里面的名字,将抽离的css合并成文件
    // 对每个入口chunk都生成一个对应的文件
    // 所以当你配置多个入口 chunk 的时候
    // 必须使用[name],[id]或[contenthash]
    new ExtractTextPlugin('css/[name].css'),
    // 压缩css
    new OptimizeCssAssetsPlugin({
      // 匹配需要压缩的文件
      assetNameRegExp: /\.css$/g,
      // 压缩使用的插件
      cssProcessor: require('cssnano'),
      cssProcessorOptions: { discardComments: {removeAll: true } },
      canPrint: true
    })
]

2.file-loader
file-loader用来解析资源文件,可以自定义解析生成的文件名,路径等等,用来处理css中的background-image以及js中import一个img等引用资源的情景。
file-loader存在一个很大的坑就是,我们往往需要使用相对路径去解析打包文件中设计的图片资源,并且将打包生成的css,images分别放在不同的目录,比如我们规定解析生成的img的路径名称为:assets/images/demo.png,那么不管是在css还是在js的img引用中,引用路径都会是'assets/images/demo.png',在html中,由于本身目录结构与asset平级,可以顺利引用,但是在css中就不行了,引用路径就会变成dist/assets/css/assets/image/demo.png。emmm,自然是不行的。在网上找了一大圈,全是什么乱七八糟的,要么牛头不对马嘴,要么自娱自乐,要么强行装逼...真是无力吐槽。真正有用的信息总是被垃圾信息掩盖,不过费了九牛二虎之力,还是找到了行之有效的解决办法,传送门。这里利用了extract-text-webpack-plugin的publicPath属性,这个属性的作用是,重新设置loader解析出来的文件的publicPath。作用就是,比如你在css里面本来的引用路径是'assets/images/demo.png',通过设置publicPath,引用路径就变成了'../../assets/images/demo.png'。根据本例的路径,(返回到assets层,再返回到dist层)最终解析的路径就是'dist/assets/images/demo.png'。ok,至此,import、url()的路径都是正常的啦。网上有一种解决方案是使用绝对路径,额,大胸弟,我觉得这个很不妥吧,你能保证你的目录外面没有嵌套个几层?比如给咱的应用套个apapa的壳?(emmmm.很偏激,欢迎指正) 可以结合图片压缩plugin,比如压缩生成的雪碧图。

{
    test: /\.(png|svg|jpe?g|gif)$/i,
    use: {
      loader: 'file-loader',
      options: {
        name: 'assets/images/[name].[ext]'
      }
    }
}

// css-loader做如下修改
{
    test: /\.css$/,
    // 它会将所有的入口 chunk(entry chunks)中引用的 *.css,
    // 移动到独立分离的 CSS 文件
    // css bundle 与 js bundle 并行加载
    use: ExtractTextPlugin.extract({
      fallback: 'style-loader',
      // 定义文件内部引用的路径
      // 原路径加上../../(基于assets/images/)
      // 用来处理url文件引用
+     publicPath: '../../',
      use: 'css-loader'
    })
}

3.babel-loader
babel-loader的作用是在webpack里面使用babel。emmm....
用法如下

{
    test: /\.(js|jsx)$/,
    exclude: /node_modules/,
    use: {
      // 依赖babel-loader,babel-core
      // 等价于
      // loader: 'babel-loader?presets=env&compact=false',
      loader: 'babel-loader',
      options: {
        // 将es6的语法转换成es5
        presets: [
          ["env", {

            // 如果兼容性要求不高,可以添加target属性
            // 减少polyfill的代码量,并且直接使用es6新特性
            "targets": {
              "browsers": ["last 2 versions", "safari >= 7"]
            },
            // 交由 Webpack 来处理模块化(决定使用import/require)
            // 通过其 TreeShaking 特性将有效减少打包出来的JS文件大小867bytes->817bytes
            "modules": false
          }]
        ],
        // babel-plugin-transform-runtime
        // babel-runtime
        // 避免模块的重复引用,polyfills功能,修复es6高级语法不兼容问题
        // 与babel-polyfill的区别在于runtime会按需加载,不会污染全局
        plugins: ['transform-runtime'],
        // 缓存编译结果
        cacheDirectory: true,
        // 去掉多余的空行与换行符
        compact: true
      }
    }
}

4.ts-loader
使用ts开发时,需要使用ts-loader进行type check,但是ts-loader在执行检测的过程中,是单线程执行,这会造成编译时间巨长无比。在这里使用awesome-typescript-loader替代

{
    test: /\.tsx?$/,
    use: {
      loader: 'awesome-typescript-loader',
      options: {
        useBabel: true,
        babelOptions: {
          babelrc: false, /* Important line */
          presets: [
            ["env", { "targets": "last 2 versions, ie 11", "modules": false }]
          ],
          // polyfill
          plugins: ['transform-runtime'],
        },
        babelCore: "babel-core", // needed for Babel v7
        errorsAsWarnings: true, // 类型错误warning,而不是error
      }
},

常用插件

1.HtmlWebpackPlugin
该插件将为你生成一个HTML5文件,其中包括使用script标签的body中的所有webpack包

new HtmlWebpackPlugin({
  // 定义html文件的title,如果指定模板则无效
  title: '我的生涯一片无悔,想起那天下午夕阳下的奔跑,那是我逝去的青春',
  favicon: './assets/images/favicon.ico',
  template: './template/page.html',
  filename: 'index.html',
  // 只引入指定的入口文件生成的chunks,默认引入所有
  chunks: ['bar'],
  // 将生成的文件插入html中的位置
  inject: 'body',
  // 给生成的js,css添加一个唯一的hash
  // assets/js/bar.js?b34fce8721458861ac22
  hash: true,
  cache: true
  
  // 使用插件,丰富template
  // 将生成的文件插入html中的位置
  // html-webpack-template结合使用时需要置为false
  // 个人觉得不好用,不够直观,不玩了
  // inject: false,
  // template: require('html-webpack-template'),
  // appMountId: 'app',
}),

2.clean-webpack-plugin
清除文件夹,比如清除之前生成的dist

// 清理dist,默认基于__dirname,可以自己传参配置,
// 如果目录在root之外,则无法顺利清除
// root需要包含被清除目录
new CleanWebpackPlugin(['dist'], {root: path.resolve(__dirname, '../')}),

3.extract-text-webpack-plugin与optimize-css-assets-webpack-plugin
分离cs压缩css

// 它会将所有的入口 chunk(entry chunks)中引用的 *.css,
// 移动到独立分离的 CSS 文件
// css bundle 与 js bundle 并行加载
test: /\.css$/,
use: ExtractTextPlugin.extract({
  fallback: 'style-loader',
  // 定义文件内部引用的路径
  // 原路径加上../../(基于assets/images/)
  // 用来处理url文件引用路径不正确问题
  publicPath: '../../',
  use: 'css-loader'
})

// name为入口里面的名字,将抽离的css合并成文件
// 所以一个入口生成一个css文件,在HtmlWebpackPlugin中
// 将根据入口将对应的css文件绑定到html
// 对每个入口chunk都生成一个对应的文件
// 所以当你配置多个入口 chunk 的时候
// 必须使用[name],[id]或[contenthash]
new ExtractTextPlugin('assets/css/[name].css'),

// 压缩css
new OptimizeCssAssetsPlugin({
  assetNameRegExp: /\.css$/g,
  cssProcessor: require('cssnano'),
  cssProcessorOptions: { discardComments: { removeAll: true } },
  canPrint: true
})

4.new webpack.optimize.UglifyJsPlugin()
压缩打包后的文件
使用插件替代uglifyjs-webpack-plugin

// 压缩打包后的文件
new UglifyJSPlugin({
  // 生产环境使用source-map
  sourceMap: true
})

5.hard-source-webpack-plugin
缓存编译结果,加速编译,效果显著

// 缓存编译结果,缩短编译时间
new HardSourceWebpackPlugin(),

概念

webpack打包的代码分成三个部分,第一个是自己编写的代码,第二部分为引入的第三方库与依赖,第三个部分是webpack用来进行模块加载与逻辑解析(runtime)和模块交互的部分(mainfest)


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • 版权声明:本文为博主原创文章,未经博主允许不得转载。 webpack介绍和使用 一、webpack介绍 1、由来 ...
    it筱竹阅读 11,025评论 0 21
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,382评论 25 707
  • 目录第1章 webpack简介 11.1 webpack是什么? 11.2 官网地址 21.3 为什么使用 web...
    lemonzoey阅读 1,731评论 0 1
  • 一开始想用permutations那种全排列来计算,DFS写了好久发现人家n可以是9位数,递归几千万次这得什么计算...
    DrunkPian0阅读 249评论 0 0
  • 【养身篇】中医说“恐伤肾”中医认为恐为肾之志长期恐惧或突然意外惊恐皆能导致肾气受损所谓恐伤肾,就是指的这个意思肾主...
    晨曦_邱月晖阅读 1,302评论 0 0