一篇文章让你快速上手Webpack4

为什么要使用Webpack

  • 转换ES6语法
  • 转换JSX
  • CSS前缀补全/预处理器
  • 压缩整合
  • 图片压缩
  • Vue/React/Anguler的解析

前端构建演变

-> ant + YUI Tool -> Grunt -> Fis3
-> Gulp -> Rollup
-> Webpack
​ -> Parcel

为什么选择Webpack

  • 社区生态丰富
  • 配置灵活和插件化扩展
  • 官方更新迭代速度快

初识Webpack

  • 默认的配置文件:webpack.config.js

    ​ 可以通过webpack –config <指定文件>

  • 配置文件组成

module.exports = {
    entry:'./src/index.js', //入口文件
    output:'./dist/main.js', //打包输出
    mode:'production', //环境
    module:{
        rules:[ //Loader配置
            {test:/\.txt$/,use:'raw-loader'}
        ]
    },
    plugins:[ //插件配置
        new HtmlwebpackPlugin({
            template:'./src/index.html'
        })
    ]
  }
  

核心概念

Entry

​ 作为入口配置,简单来说就从哪个文件开始打包。

用法:

  • 单入口
  module.exports={
    entry:'./path/file.js'
  }
  • 多入口
  module.exports={
    entry:{
        app:'./src/app.js',
        adminApp:'./src/adminApp.js'
    }
  }

Output

​ 将打包后的文件输出到哪里。

用法:

  • 单出口
  module.exports={
    entry:'./path/file.js',
    output:{
          filename:'bundle.js',
          path:__dirname+'/dist'
    }
  }
  • 多出口
  module.exports={
    entry:{
        app:'./src/app.js',
        adminApp:'./src/adminApp.js'
    },
      output:{
        filename:'[name].js',
          path:__dirname+'/dist'
    }
  }

Loaders

​ webpack开箱即用只支持js和json这两种文件类型。像VUE,JSX这些webpack是不支持的,所以就有了Loader。简单来说Loaders就是处理文件的。

​ Loader本身就是一个函数,接收源文件作为参数然后在返回结果。

常见Loader

名称 描述
babel-loader 转换ES5+的语法(需要babel的配合)
css-loader 支持css文件的加载解析
less-loader 将less转为css
ts-loader 将ts转为js
file-loader 将文件(图片、字体)等打包
raw-loader 将文件以字符串形式导入
thread-loader 多进程打包js和css
url-loader 与file-loader功能一样,但是他是可以配置的,简单来说升级版file-loader

用法

module.exports = {
    entry:'./src/index.js', //入口文件
    output:'./dist/main.js', //打包输出
    mode:'production', //环境
    module:{
        rules:[ //Loaders配置
            {test:/\.txt$/,use:'raw-loader'}
        ]
    }
}

Plugins

​ 增强Webpack的功能,将打包后的文件进行优化、资源管理、环境变量的注入等待。简单来说就是Loaders做不了的用Plugins来做。

​ 作用用整个构建过程。

常用的插件

名称 描述
CommonsChunkPlugin 将多个出口引用相同的文件进行提取。
CleanWebpackPlugin 清理构建目录
ExtractTextWebpackPlugin 将css从bundle中提取成一个独立的css文件
CopyWebpackPlugin 将文件或文件夹拷贝到构建的目录中
HtmlWebpackPlugin 创建html文件去承载bundle
UglifyjsWebpackPlugin 压缩js(默认是开启的不需要配置)
ZipWebpackPlugin 将构建资源生成为zip包
HotModuleReplacementPlugin 热更新
MiniCssExtractPlugin 将css提取成独立的文件(与style-loader会产生冲突)
OptimizeCssAssetsWebpackPlugin 用于压缩css(配合 cssnano 加载器使用)

说明:安装插件时要将所有的大写改为小写并且在非第一个大写字母前加短横线-。

用法

module.exports = {
    entry:'./src/index.js', //入口文件
    output:'./dist/main.js', //打包输出
    mode:'production', //环境
    module:{
        rules:[ //Loader配置
            {test:/\.txt$/,use:'raw-loader'}
        ]
    },
    plugins:[ //插件配置
        new HtmlwebpackPlugin({
            template:'./src/index.html'
        })
    ]
}

Mode

​ mode是在webpack4提出的一个概念,通过mode来指定当前的构建环境,比如:你现在是development(开发)环境,或者是production(生成环境默认).

选项 描述
development 开发环境
production 生产环境
none 不开启

例子

解析ES6

# 安装依赖
npm i -g webpack webpack-cli
npm i -D @babel/core @babel/preset-env babel-loader
# @babel/core       babel核心文件(必须安装)
# @babel/preset-env babel用来转换ES5
# babel-loader      webpack的loader,调用babel的
//webpack.config.js
module.exports={
    entry:"./src/app.js",
    output:{
        filename:bundle.js,
        path:__dirname+'/dist'
    },
    mode:'development',
    module:{
        rules:[
            {
                test:/.js$/,
                use:'babel-loader'
            }
        ]
    }
}
//.babelrc
{
    "presets":[
        "@babel/preset-env"
    ]
}

解析CSS

# 安装依赖
npm i css-loader style-loader -D
# css-loader    将css文件打包成commonjs对象
# style-loader  将css-loader打包好的样式通过<style>标签插入到head中
//webpack.config.js
module.exports={
    entry:"./src/app.js",
    output:{
        filename:"bundle.js",
        path:__dirname+"/dist"
    },
    mode:"development",
    module:{
        rules:[
            {
                test:/.js$/,
                use:'babel-loader'
            },
            {
                test:/.css$/,
                use:[
                    'style-loader',
                    'css-loader'
                ]
                /*注意:
                use内的loader执行是从下到上的,
                所以先执行css-loader然后才是style-loader*/
            }
        ]
    }
}

解析Less

# 安装依赖
npm i css-loader style-loader less-loader less -D
# css-loader    将css文件打包成commonjs对象
# style-loader  将css-loader打包好的样式通过<style>标签插入到head中
# less-loader   是将less转成css
# less          less核心(必装),less-loader依赖
//webpack.config.js
module.exports={
    entry:"./src/app.js",
    output:{
        filename:"bundle.js",
        path:__dirname+"/dist"
    },
    mode:"development",
    module:{
        rules:[
            {
                test:/.js$/,
                use:'babel-loader'
            },
            {
                test:/.less$/,
                use:[
                    'style-loader',
                    'css-loader',
                    'less-loader'
                ]
                /*注意:
                use内的loader执行是从下到上的,
                首先将less转换成css
                然后将css转换成js
                然后将js封装为style标签
            }
        ]
    }
}

解析文件

# 安装依赖
npm i css-loader style-loader file-loader -D
# css-loader    将css文件打包成commonjs对象
# style-loader  将css-loader打包好的样式通过<style>标签插入到head中
# file-loader   将文件解析
//webpack.config.js
module.exports={
    entry:"./src/app.js",
    output:{
        filename:"bundle.js",
        path:__dirname+"/dist"
    },
    mode:"development",
    module:{
        rules:[
            {
                test:/.js$/,
                use:'babel-loader'
            },
            {
                test:/.css/,
                use:[
                    'style-loader',
                    'css-loader'
                ]
                /*注意:
                use内的loader执行是从下到上的,
                首先将less转换成css
                然后将css转换成js*/
            },
            {
                test:/.(png|jpg|gif|jpeg|ttf|eot)$/,
                use:[
                    'file-loader'
                ]
            }
        ]
    }
}

更好的解析文件

# 安装依赖
npm i css-loader style-loader url-loader -D
# css-loader    将css文件打包成commonjs对象
# style-loader  将css-loader打包好的样式通过<style>标签插入到head中
# url-loader    更好的文件解析,代替file-loader
//webpack.config.js
module.exports={
    entry:"./src/app.js",
    output:{
        filename:"bundle.js",
        path:__dirname+"/dist"
    },
    mode:"development",
    module:{
        rules:[
            {
                test:/.js$/,
                use:'babel-loader'
            },
            {
                test:/.css/,
                use:[
                    'style-loader',
                    'css-loader'
                ]
                /*注意:
                use内的loader执行是从下到上的,
                首先将less转换成css
                然后将css转换成js*/
            },
            {
                test:/.(png|jpg|gif|jpeg|ttf|eot)$/,
                use:[
                    {
                        loader:'url-loader',
                        options:{
                            limit:10240 //单位B
                        }
                        /*
                            url-loader 与file-loader功能一样,不过他有一定很不错,
                            可以传入参数:
                                limit:单位字节,如果文件小于给定的字节大小,就进行
                                base64转换
                        */
                    }
                ]
            }
        ]
    }
}

自动打包

两种方法:

  • 命令行:webpack —watch
  • 配置文件:watch:true

原理:

​ webpack轮询(每隔一定的时间)对当前文件夹下的文件的修改时间进行监听,如果某个文件发生了变化,webpack不会立即打包而是在缓存时间到后才去打包。

//webpack.config.js
module.export = {
    watch:true,//开启监听
    watchOptions:{
        ignored:/node_modules/.//默认为空,表示不对什么文件夹或文件监听,支持正则表达式        aggregateTimeout:300,//监听触发后等300ms后执行打包,默认300ms
        poll:1000,//轮询时间,单位ms
    }
}

热重载

方法一

webpack-dev-server开发者服务

优势:

  • webpack-dev-server不刷新浏览器
  • webpack-dev-server文件放到内存

依赖插件:

​ HotModuleReplacementPlugin

​ HMRP 是将打包后的文件放到内存里,通过websocket将内容发给浏览器,实现热重载。

操作:

//webpack.config.js
const {HotModuleReplacementPlugin} = require('webpack');

module.exports={
    entry:"./src/app.js",
    output:{
        filename:"bundle.js",
        path:__dirname+"/dist"
    },
    mode:"development",
    module:{
        rules:[
            {
                test:/.js$/,
                use:'babel-loader'
            },
            {
                test:/.less$/,
                use:[
                    'style-loader',
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test:/.(png|jpg)$/,
                use:[
                    {
                        loader:'url-loader',
                        options:{
                            linmit:1024
                        }
                    }
                ]
            }
        ]
    },
    plugins:[
        new HotModuleReplacementPlugin()
    ],
    devServer:{
        contentBase:'./dist',//服务器根目录
        hot:true //是否热重载
    }
}
# 执行命令
npm i webpack-dev-server -g
webpack-dev-server --open
# --open 表示打开浏览器

方法二

/**
 * 另一种热重载的方法
 */
const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const app = express();

const config = require('./webpack.config');

app.use(webpackDevMiddleware(
    webpack(config),
    {
        publicPath:config.output.publicPath
    }
    ));

app.listen(8080, () => {
    console.log('Example app listening on port 8080!');
});

//Run app, then load http://localhost:8080 in a browser to see the output.

文件指纹

​ 打包后输出的文件名额外添加的后缀字符。

有什么用:
  • 文件的版本管理。
  • 文件缓存。
文件指纹如何生成
  • hash:根据修改时间生成。
  • chunkhash:根据entry生成。
  • contenthash:根据文件内容生成。
如何用
占位符 含义
[ext] 后缀名
[name] 文件名称
[path] 文件的相对路径
[chunkhash] 根据entry生成hash
[folder] 文件所在的文件夹
[contenthash] 文件内容hash,默认md5
[hash] 同上
[emoji] 随机字符串

说明:[hash:8] 8表示截取前8位。

/**
 * 生产环境配置
 */
const MiniCssExtractPulgin = require('mini-css-extract-plugin');

module.exports={
    entry:"./src/app.js",
    output:{
        filename:"bundle_[chunkhash:8].js",
        path:__dirname+"/dist"
    },
    mode:"production",
    module:{
        rules:[
            {
                test:/.js$/,
                use:'babel-loader'
            },
            {
                test:/.less$/,
                use:[
                    MiniCssExtractPulgin.loader,/*注意,这个loader时插件提供的*/
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test:/.(png|jpg)$/,
                use:[
                    {
                        loader:'file-loader',
                        options:{
                            name:'./img/[name]_[hash:8].[ext]'
                        }
                    }
                ]
            }
        ]
    },
    plugins:[
        new MiniCssExtractPulgin({
            filename:'[name]_[contenthash:8].css'
        })
    ]
}

文件压缩

​ 文件压缩是将打包后的html、css、js文件进行压缩。

JS压缩

​ 使用UglifyjsWebpackPlugin这个插件进行压缩,webpack4生成环境下默认是开启的所以不需要配置。

CSS压缩

​ 需要OptimizeCssAssetsWebpackPlugin插件

​ 需要cssnanoCSS压缩加载器(核心)

# 安装依赖
npm i -D optimize-css-assets-webpack-plugin cssnano
//webpack.config.js
/**
 * 生产环境配置
 */
const MiniCssExtractPulgin = require('mini-css-extract-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');

module.exports={
    entry:"./src/app.js",
    output:{
        filename:"bundle_[chunkhash:8].js",
        path:__dirname+"/dist"
    },
    mode:"production",
    module:{
        rules:[
            {
                test:/.js$/,
                use:'babel-loader'
            },
            {
                test:/.less$/,
                use:[
                    MiniCssExtractPulgin.loader,
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test:/.(png|jpg)$/,
                use:[
                    {
                        loader:'file-loader',
                        options:{
                            name:'./img/[name]_[hash:8].[ext]'
                        }
                    }
                ]
            }
        ]
    },
    plugins:[
        new MiniCssExtractPulgin({
            filename:'[name]_[contenthash:8].css'
        }),
        new OptimizeCssAssetsWebpackPlugin({
            /*作用于打包后的文件*/
            assetNameRegExp:/.css$/g,
            /*匹配打包后的文件*/
            cssProcessor:require('cssnano')
            /*使用cssnano压缩处理器*/
        })
        /*
            注意:是先有打包文件,才能进行压缩。
        */
    ]
}  

HTMlL压缩

​ 通过使用HtmlWebpackPlugin,设置参数进行压缩。

html-webpack-plugin配置表:

Name Type Default Description
title {String} `` 用于生成的HTML文档的标题
filename {String} 'index.html' 要写入HTML的文件。默认为“index . html”。您也可以在这里指定子目录 (eg: assets/admin.html)
template {String} `` webpack 需要模板的路径。Please see the docs for details
templateParameters {Boolean|Object|Function} `` 允许覆盖模板中使用的参数。
inject {Boolean|String} true true || 'head' || 'body' || false 将所有资产注入给定的模板”或“templateContent”。当传递“true”或“body”时所有javascript资源都将放在body元素的底部。'head'`将脚本放在head元素中
favicon {String} `` 将给定的favicon路径添加到输出HTML
meta {Object} {} 允许注入“meta”标签。 E.g. meta: {viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'}
minify {Boolean|Object} true 传递html-minifier的选项作为对象来缩小输出
hash {Boolean} false 如果“true”,则在所有包含的脚本和CSS文件中附加一个惟一的“webpack”编译散列。这对于缓存破坏非常有用
cache {Boolean} true 只有在文件被更改时才发出该文件
showErrors {Boolean} true 错误细节将被写入HTML页面
chunks {?} ? 允许您只添加一些块(e。g只是单元测试块)
chunksSortMode {String|Function} auto 允许控制块在包含到HTML之前应该如何排序。允许的值是 'none' | 'auto' | 'dependency' | 'manual' | {Function}
excludeChunks {Array.<string>} `` 允许你跳过一些块(e.g不要添加单元测试块)
xhtml {Boolean} false 如果“true”将“link”标记呈现为自关闭(XHTML兼容)

miniify配置表:

默认情况下,大多数选项都是禁用的。

Option Description Default
caseSensitive 以区分大小写的方式处理属性(对自定义HTML标记很有用) false
collapseBooleanAttributes 从布尔属性中省略属性值 false
collapseInlineTagWhitespace 折叠时,不要在display:inline;元素之间留下任何空格。必须与collapseWhitespace = true一起使用 false
collapseWhitespace 折叠有助于文档树中文本节点的空白 false
conservativeCollapse 始终折叠到1个空格(永远不要完全删除)。必须与collapseWhitespace = true 一起使用FALSE
continueOnParseError 处理解析错误 而不是流失。 false
customAttrAssign 允许支持自定义属性赋值表达式的正则表达式数组(e.g. '<div flex?="{{mode != cover}}"></div>') [ ]
customAttrCollapse 正则表达式,指定从中删除换行符的自定义属性 (e.g. /ng-class/)
customAttrSurround 允许支持自定义属性环绕表达式的正则表达式数组 (e.g. <input {{#if value}}checked="checked"{{/if}}>) [ ]
customEventAttributes 允许支持自定义事件属性的正则表达式数组minifyJS (e.g. ng-click) [ /^on[a-z]{3,}$/ ]
decodeEntities 尽可能使用直接Unicode字符 false
html5 根据HTML5规范解析 true
ignoreCustomComments 一组正则表达式,允许在匹配时忽略某些注释 [ /^!/ ]
ignoreCustomFragments 允许在匹配时忽略某些片段的正则表达式数组 (e.g. <?php ... ?>, {{ ... }}, etc.) [ /<%[\s\S]*?%>/, /<\?[\s\S]*?\?>/ ]
includeAutoGeneratedTags 插入HTML解析器生成的标签 true
keepClosingSlash 在单例元素上保留尾部斜杠 false
maxLineLength 指定最大行长度。压缩输出将在有效HTML分割点处按换行符分割
minifyCSS 在样式元素和样式属性中缩小CSS (uses clean-css) false (可能 true, Object, Function(text, type))
minifyJS 缩小脚本元素和事件属性中的JavaScript(使用 UglifyJS) false (could be true, Object, Function(text, inline))
minifyURLs 缩小各种属性中的URL(uses relateurl) false (could be String, Object, Function(text))
preserveLineBreaks 当标记之间的空格包含换行符时,始终折叠为1换行符(从不完全删除它)。必须与collapseWhitespace = true一起使用 false
preventAttributesEscaping 防止转义属性值 false
processConditionalComments 通过minifier处理条件注释的内容 false
processScripts 与通过缩小器处理的脚本元素类型相对应的字符串数组(例如text/ng-template, text/x-handlebars-template, etc.) [ ]
quoteCharacter 用于属性值的引用类型(
removeAttributeQuotes 尽可能删除属性周围的引号 false
removeComments 剥离HTML注释 false
removeEmptyAttributes 使用仅限空格的值删除所有属性 false (could be true, Function(attrName, tag))
removeEmptyElements 删除所有带空内容的元素 false
removeOptionalTags 删除可选标签 false
removeRedundantAttributes 值匹配默认值时删除属性. false
removeScriptTypeAttributes script标签中删除type =“text /javascript”。其他type属性值保持不变false
removeStyleLinkTypeAttributes stylelink标签中删除type =“text /css”。其他type属性值保持不变false
removeTagWhitespace 尽可能删除属性之间的空间。 请注意,这将导致HTML无效! FALSE
sortAttributes 按频率对属性排序 false
sortClassName 按频率对样式类进行排序 false
trimCustomFragments 修剪ignoreCustomFragments周围的空白区域。 false
useShortDoctype 用短(HTML5)doctype替换doctype false
//webpack.config.js
/**
 * 生产环境配置
 */
const MiniCssExtractPulgin = require('mini-css-extract-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');

module.exports={
    entry:{index:"./src/app.js"},
    output:{
        filename:"bundle_[chunkhash:8].js",
        path:__dirname+"/dist"
    },
    mode:"production",
    module:{
        rules:[
            {
                test:/.js$/,
                use:'babel-loader'
            },
            {
                test:/.less$/,
                use:[
                    MiniCssExtractPulgin.loader,
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test:/.(png|jpg)$/,
                use:[
                    {
                        loader:'file-loader',
                        options:{
                            name:'./img/[name]_[hash:8].[ext]'
                        }
                    }
                ]
            }
        ]
    },
    plugins:[
        new MiniCssExtractPulgin({
            filename:'[name]_[contenthash:8].css'
        }),
        new OptimizeCssAssetsWebpackPlugin({
            assetNameRegExp:/.css$/g,
            cssProcessor:require('cssnano')
        }),
        new HtmlWebpackPlugin({
            title:'webpack学习',
            template:path.join(__dirname,'src/index.html'),
            filename:'index.html',
            chunks:['index'],
            /**
             * 这里需要注意一下,如果entry写法是这样的:{index:'src/index.js'}那这里就需要使用chunks:['index']
             * 如果entry写法是: 'src/index.js' 那这里就不需要使用chunks
             * 
             * 如果不按照上面的规定,下面的inject:true将不会生效
             */
            inject:true,
            /**自动注入js与css */
            minify:{
                html5:true,
                collapseWhitespace:true,
                preserveLineBreaks:false,
                minifyCSS:true,
                minifyJS:true,
                removeComments:false
            }
        })
    ]
}

结束

到这里webpack的基础用法已经写完了,接下来我会继续更新,webpack的进阶用法。

如果你感觉我的文章对你有用,你可以点下面的大拇指给我鼓励,谢谢。

如果想要转载,请标明出处

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

推荐阅读更多精彩内容

  • 1. 新建一个文件夹,命名为 webpack-cli , webpack-cli 就是你的项目名,项目名建议使用小...
    鲁大师666阅读 1,474评论 1 3
  • 前言 本文主要从webpack4.x入手,会对平时常用的Webpack配置一一讲解,各个功能点都有对应的详细例子,...
    BetterChen阅读 1,949评论 0 3
  • 本项目基于 入门 Webpack,看这篇就够了创建。本例程通过从头构建一个基于npm管理的前端项目,一步步的让读者...
    尤利西斯U阅读 2,772评论 0 8
  • 前端将大型项目分成一个个单独的模块,一般封装好的每个模块都会实现一个目的明确的完成的功能。如何处理这些模块以及模块...
    pixels阅读 3,425评论 1 14
  • 一年一度的重大考试——高考,又落下帷幕。相信每一个考生现在都如释重负,因为紧绷了一年的神经终于放松了。但是高考并不...
    爱姣一生阅读 647评论 6 11