使用原因:
1.有一个很大的单页应用,为了提高开发效率,要将这个项目拆成多个模块,开发完成后,这个项目可以正常跑了。但是因为多个模块是存在不同文件中的,因此加载这个单页应用时,会发出多次请求。这时我们希望能够把所有模块打包成一个文件,这样可以减少请求次数,提升体验。
2.在开发这个单页应用中,同样是为了提高开发效率,使用了一些js和css的扩展语言,如TypeScript及Less、stylus,这些扩展使我们可以更简洁优雅地写代码,但是开发完成开始部署时,需要将它们进行相应的转换,转换成浏览器支持的语言。这时,我们希望能够有个工具可以以很大的自动化程度去完成这个转换工作。
3.在这个单页应用开发完成后,我们为了提高其性能,希望做一些列处理,比如把js进行压缩。
简单使用:
npm init 生成package.json文件
-
npm install webpack -g // 全局安装
-
npm install webpack --save-dev // 只在当前项目里安装
写webpack配置项文件
在项目根目录创建名为webpack.config.js的文件
var webpack = require('webpack');(引入)
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: {} ,
output: {} ,
module:{
loaders:[],
noParse:[]
},
plugins:[],
resolve:{}
devtool:'',
watch:boolean,
devServer:{}
}
module.exports = {
// 入口文件路径,__dirname是根目录
entry: __dirname + '/src/main.js', 要打包的文件
// 打包生成文件
output: {
path:__dirname + '/public'
, //通过HtmlWebpackPlugin插件生成的html文件存放在这个目录下面
filename:'/js/[name].js'
, //编译生成的js文件存放到根目录下面的js目录下面,如果js目录不存在则自动创建
/*
* chunkFilename用来打包require.ensure方法中引入的模块,如果该方法中没有引入任何模块则不会生成任何chunk块文件
* 比如在main.js文件中,require.ensure([],function(require){alert(11);}),这样不会打包块文件
* 只有这样才会打包生成块文件require.ensure([],function(require){alert(11);require('./greeter')})
* 或者这样require.ensure(['./greeter'],function(require){alert(11);})
* chunk的hash值只有在require.ensure中引入的模块发生变化,hash值才会改变
* 注意:对于不是在ensure方法中引入的模块,此属性不会生效,只能用CommonsChunkPlugin插件来提取
* */
chunkFilename:'js/[chunkhash:8].chunk.js'
chunkname:个人理解chunkname就是未被列在entry中,但有些场景需要被打包出来的文件命名配置。比如按需加载(异步)模块的时候,这样的文件是没有被列在entry中的使用CommonJS的方式异步加载模块。
在require.ensure去加载模块的时候才会出现,chunkFileName,个人理解是cmd和amd异步加载,而且没有给入口文件时,会生成了no-name的chunk,所以你看到的例子,chunkFileName一般都会是[id].[chunkhash].js,也就是这种chunk的命名一般都会是0.a5898fnub6.js
非入口文件的命名规则
},
plugins: [
new HtmlWebpackPlugin()
]
}
1、
css-loader & style-loader(loader只需要安装)(针对css)
npm install --save-dev style-loader css-loader
module.exports = {
entry: __dirname + '/src/main.js',
output: {
path: __dirname + '/output',
filename: 'main.js'
},
module: {
loaders: [
{
test: /\.css$/,
loader: 'style-loaer!css-loader'
}
]
}
}
2、file-loader 和 url-loader(安装url-loader即可)(针对img还有文件)
如果我们希望在页面引入图片(包括img的src和background的url)。当我们基于webpack进行开发时,引入图片会遇到一些问题。
其中一个就是引用路径的问题。拿background样式用url引入背景图来说,我们都知道,webpack最终会将各个模块打包成一个文件,因此我们样式中的url路径是相对入口html页面的,而不是相对于原始css文件所在的路径的。这就会导致图片引入失败。这个问题是用file-loader解决的,file-loader可以解析项目中的url引入(不仅限于css),根据我们的配置,将图片拷贝到相应的路径,再根据我们的配置,修改打包后文件引用路径,使之指向正确的文件。
另外,如果图片较多,会发很多http请求,会降低页面性能。这个问题可以通过url-loader解决。url-loader会将引入的图片编码,生成dataURl。相当于把图片数据翻译成一串字符。再把这串字符打包到文件中,最终只需要引入这个文件就能访问图片了。当然,如果图片较大,编码会消耗性能。因此url-loader提供了一个limit参数,小于limit字节的文件会被转为DataURl,大于limit的还会使用file-loader进行copy。
url-loader和file-loader是什么关系呢?简答地说,url-loader封装了file-loader。url-loader不依赖于file-loader,即使用url-loader时,只需要安装url-loader即可,不需要安装file-loader,因为url-loader内置了file-loader。通过上面的介绍,我们可以看到,url-loader工作分两种情况:1.文件大小小于limit参数,url-loader将会把文件转为DataURL;2.文件大小大于limit,url-loader会调用file-loader进行处理,参数也会直接传给file-loader。因此我们只需要安装url-loader即可。
例1:
{
test: /\.jpeg$/,
use: [
{
loader: 'url-loader',
options: {
limit: '1024'
}
},
]
}
例2:
{
test: /\.(woff|woff2|ttf|eot|svg)(\?t=[0-9]+)?$/,
loader: 'file-loader?name=./fonts/[name].[ext]'
放在output中指定的路径下的fonts文件夹下,名字还是name,后缀是原本的test
}
, {
test: /\.(woff|woff2|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?|(woff|woff2|ttf|eot)$/,
loader: 'file-loader?name=./fonts/[name].[ext]'
}, {
test: /\.(png|jpg|gif)$/,
loader: 'url-loader',
query: {limit: 8192}
}
例3:
{
test: /\.jpeg$/,
// use: 'url-loader?limit=1024&name=[path][name].[ext]&publicPath=output/',
use: 'url-loader?limit=1024&name=[path][name].[ext]&outputPath=img/&publicPath=output/',
},
limit、name、outputPath、publicPath。其中limit已经说明过。file-loader相关的是name、outputPath和publicPath。下面解释一下这3个参数
name表示输出的文件名规则,如果不添加这个参数,输出的就是默认值:文件哈希。加上[path]表示输出文件的相对路径与当前文件相对路径相同,加上[name].[ext]则表示输出文件的名字和扩展名与当前相同。加上[path]这个参数后,打包后文件中引用文件的路径也会加上这个相对路径。
outputPath表示输出文件路径前缀。图片经过url-loader打包都会打包到指定的输出文件夹下。但是我们可以指定图片在输出文件夹下的路径。比如outputPath=img/,图片被打包时,就会在输出文件夹下新建(如果没有)一个名为img的文件夹,把图片放到里面。
publicPath表示打包文件中引用文件的路径前缀,如果你的图片存放在CDN上,那么你上线时可以加上这个参数,值为CDN地址,这样就可以让项目上线后的资源引用路径指向CDN了。
3、autoprefixer-loader(loader只需安装即可)(给css自动添加前缀)
写css样式时,有些情况下需要加样式前缀以兼容不同的浏览器。手动添加css前缀会写较多的重复代码,降低开发效率。autoprefixer-loader为我们提供了自动添加css前缀的功能。
npm install --save-dev autoprefixer-loader
{
test: /\.jpeg$/,
// use: 'url-loader?limit=1024&name=[path][name].[ext]&publicPath=output/',
use: 'url-loader?limit=1024&name=[path][name].[ext]&outputPath=img/&publicPath=output/',
},
4、less-loader(less)
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'autoprefixer-loader',
'less-loader'
]
},
5、extract-text-webpack-plugin(插件需要引入)(防止css在js中错乱)
该插件的主要是为了抽离css样式,防止将样式打包在js中引起页面样式加载错乱的现象
npm install extract-text-webpack-plugin --save-dev
例1:
const ExtractTextPlugin = require("extract-text-webpack-plugin");(引入)
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
}
]
},
plugins: [
new ExtractTextPlugin("styles.css"),
]
}
use:指需要什么样的loader去编译文件,这里由于源文件是.css所以选择css-loader
fallback:编译后用什么loader来提取css文件
publicfile:用来覆盖项目路径,生成该css文件的文件路径
例2:
const ExtractTextPlugin = require("extract-text-webpack-plugin");(引入)
module: {
rules: [
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader')
},
]
},
plugins: [
new ExtractTextPlugin('css/[name].css')
],
例3:
module: {
rules: [
{
test: /\.less$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
'css-loader',
'autoprefixer-loader',
'less-loader'
]
})
}
]
},
例4:
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var extractCss = new ExtractTextPlugin('[name]-one.css');
var extractLess = new ExtractTextPlugin('[name]-two.css');
plugins: [
extractCss,
extractLess
]
为了让打包后样式生效,有两种方法,一种是使用style-loader自动将css代码放到生成的style标签中插入到head标签里。另一种就是,使用extract-text-webpack-plugin插件,将样式文件单独打包,打包输出的文件由配置文件中的output属性指定。然后我们在入口HTML页面写个link标签引入这个打包后的样式文件。
插件和loader类似都是文件处理程序,但和loader不同,它不是针对特定类型文件的处理程序,而是在打包的整个过程这个更大的维度上起作用的处理程序。比如,js压缩插件UglifyJsPlugin就是把打包后的js代码进行压缩。还有这篇文章要介绍的插件extract-text-webpack-plugin是把样式文件单独打包。
6、webpack-parallel-uglify-plugin(插件)(压缩js)
npm i -D webpack-parallel-uglify-plugin
// 引入 ParallelUglifyPlugin 插件
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
module.exports = {
plugins: [
// 使用 ParallelUglifyPlugin 并行压缩输出JS代码
new ParallelUglifyPlugin({
// 传递给 UglifyJS的参数如下:
uglifyJS: {
output: {
/*
是否输出可读性较强的代码,即会保留空格和制表符,默认为输出,为了达到更好的压缩效果,
可以设置为false
*/
beautify: false,
/*
是否保留代码中的注释,默认为保留,为了达到更好的压缩效果,可以设置为false
*/
comments: false
},
compress: {
/*
是否在UglifyJS删除没有用到的代码时输出警告信息,默认为输出,可以设置为false关闭这些作用
不大的警告
*/
warnings: false,
/*
是否删除代码中所有的console语句,默认为不删除,开启后,会删除所有的console语句
*/
drop_console: true,
/*
是否内嵌虽然已经定义了,但是只用到一次的变量,比如将 var x = 1; y = x, 转换成 y = 5, 默认为不
转换,为了达到更好的压缩效果,可以设置为false
*/
collapse_vars: true,
/*
是否提取出现了多次但是没有定义成变量去引用的静态值,比如将 x = 'xxx'; y = 'xxx' 转换成
var a = 'xxxx'; x = a; y = a; 默认为不转换,为了达到更好的压缩效果,可以设置为false
*/
reduce_vars: true
}
}
}),
]
}
在通过 new ParallelUglifyPlugin() 实列化时,支持以下参数配置如下:
test: 使用正则去匹配哪些文件需要被 ParallelUglifyPlugin 压缩,默认是 /.js$/.
include: 使用正则去包含被 ParallelUglifyPlugin 压缩的文件,默认为 [].
exclude: 使用正则去不包含被 ParallelUglifyPlugin 压缩的文件,默认为 [].
cacheDir: 缓存压缩后的结果,下次遇到一样的输入时直接从缓存中获取压缩后的结果并返回,cacheDir 用于配置缓存存放的目录路径。默认不会缓存,想开启缓存请设置一个目录路径。
workerCount:开启几个子进程去并发的执行压缩。默认是当前运行电脑的 CPU 核数减去1。
sourceMap:是否为压缩后的代码生成对应的Source Map, 默认不生成,开启后耗时会大大增加,一般不会将压缩后的代码的
sourceMap发送给网站用户的浏览器。
uglifyJS:用于压缩 ES5 代码时的配置,Object 类型,直接透传给 UglifyJS 的参数。
uglifyES:用于压缩 ES6 代码时的配置,Object 类型,直接透传给 UglifyES 的参数。
new ParallelUglifyPlugin({
uglifyJS: {},
test: /.js$/g,
include: [],
exclude: [],
cacheDir: '',
workerCount: '',
sourceMap: false
});
7、html-webpack-plugin(插件)(生成html)
npm i --save-dev html-webpack-plugin
例1:
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: 'index.js',
output: {
path: __dirname + '/dist',
filename: 'index_bundle.js'
},
plugins: [
new HtmlWebpackPlugin()
]
}
例2:
var htmlWebpackPlugin = require('html-webpack-plugin')
const path = require('path')
module.exports = {
entry: './src/script/main.js',
output: {
filename: 'js/bundle.js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new htmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: 'head'
})
]
}
inject有四个值: true
body
head
false
true
默认值,script标签位于html文件的 body 底部body
script标签位于html文件的 body 底部head
script标签位于html文件的 head中false
不插入生成的js文件,这个几乎不会用到的
favicon
给你生成的html文件生成一个 favicon
,值是一个路径
plugins: [
new HtmlWebpackPlugin({
...
favicon: 'path/to/my_favicon.ico'
})
然后再生成的html中就有了一个 link
标签
<link rel="shortcut icon" href="example.ico">
minify
使用minify会对生成的html文件进行压缩。默认是false。html-webpack-plugin内部集成了 html-minifier
,因此,还可以对minify进行配置:(注意,虽然minify支持BooleanObject,但是不能直接这样写:minify: true , 这样会报错 ERROR in TypeError: Cannot use 'in' operator to search for 'html5' in true
, 使用时候必须给定一个 { }
对象 )
minify:{ removeComments: true,//删除注释 collapseWhiteSpace: true//删除空格 }
...
plugins: [
new HtmlWebpackPlugin({
...
minify: {
removeAttributeQuotes: true // 移除属性的引号
}
})
]
cache
默认是true的,表示内容变化的时候生成一个新的文件。
showErrors
当webpack报错的时候,会把错误信息包裹再一个pre
中,默认是true。
chunks
chunks主要用于多入口文件,当你有多个入口文件,那就回编译后生成多个打包后的文件,那么chunks
就能选择你要使用那些js文件
entry: {
index: path.resolve(__dirname, './src/index.js'),
devor: path.resolve(__dirname, './src/devor.js'),
main: path.resolve(__dirname, './src/main.js')
}
plugins: [
new httpWebpackPlugin({
chunks: ['index','main']
})
]
那么编译后:
<script type=text/javascript src="index.js"></script>
<script type=text/javascript src="main.js"></script>
- 如果你没有设置chunks选项,那么默认是全部显示
excludeChunks
排除掉一些js
excludeChunks: ['devor.js']
// 等价于上面的
xhtml
一个布尔值,默认值是 false ,如果为 true ,则以兼容 xhtml 的模式引用文件。
chunksSortMode
script的顺序,默认四个选项: none
auto
dependency
{function}
'dependency' 不用说,按照不同文件的依赖关系来排序。
'auto' 默认值,插件的内置的排序方式,具体顺序....
'none' 无序
{function} 提供一个函数
8、html-loader(html中的src)
在处理html上比较困难,不识别html中img标签src引入的图片。
html-webpack-plugin这种插件辅助处理html非常好,但却仍然未解决html代码中的图片问题,未免美中不足
{
test: /\.html$/,
loader: "html?attrs=img:src img:data-src"
}
9.babel-loader(将es6转化成es5)
babel-loader转化ES6代码
npm install babel-core babel-loader babel-preset-es2015 babel-plugin-transform-runtime --save-dev
{
test: /\.js$/,
exclude: /(node_modules|lib)/,
loader: 'babel-loader',
query: {
cacheDirectory: true,
presets: ['es2015'],
plugins: ['transform-runtime', 'transform-remove-strict-mode']
}
presets: ['es2015'] 所以安装 babel-preset-es2015
'presets': [latest]所以安装babel-preset-latest
plugins: ['transform-runtime', 'transform-remove-strict-mode']所以安装 babel-plugin-transform-runtime和 babel-plugin-transform-remove-strict-mode 取消严格模式
babel 编译时只转换语法,几乎可以编译所有时新的 JavaScript 语法,但并不会转化BOM里面不兼容的API
比如 Promise,Set,Symbol,Array.from,async 等等的一些API
这时候就需要 polyfill 来转转化这些API
babel polyfill 有三种:
* babel-runtime
* babel-plugin-transform-runtime
* babel-polyfill
transform-runtime
在使用webpack打包时,需配置到babel中
"plugins": [
["transform-runtime", {
"helpers": false,
"polyfill": false,
"regenerator": true,
"moduleName": "babel-runtime"
}]
]
transform-runtime 会有几个配置项,不表标注默认为true
在webpack中,babel-plugin-transform-runtime 实际上是依赖babel-runtime
因为babel编译es6到es5的过程中,babel-plugin-transform-runtime这个插件会自动polyfill es5不支持的特性,
这些polyfill包就是在babel-runtime这个包里
core-js 、regenerator等 poiiyfill
babel-runtime和 babel-plugin-transform-runtime的区别是,相当一前者是手动挡而后者是自动挡,每当要转译一个api时都要手动加上require('babel-runtime'),
而babel-plugin-transform-runtime会由工具自动添加,主要的功能是为api提供沙箱的垫片方案,不会污染全局的api,因此适合用在第三方的开发产品中。
runtime转换器插件主要做了三件事:
* 当你使用generators/async方法、函数时自动调用babel-runtime/regenerator
* 当你使用ES6 的Map或者内置的东西时自动调用babel-runtime/core-js
* 移除内联babel helpers并替换使用babel-runtime/helpers来替换
transform-runtime优点
* 不会污染全局变量
* 多次使用只会打包一次
* 依赖统一按需引入,无重复引入,无多余引入
transform-runtime缺点
* 不支持实例化的方法Array.includes(x) 就不能转化
* 如果使用的API用的次数不是很多,那么transform-runtime 引入polyfill的包会比不是transform-runtime 时大
总的来说一句话,你可以使用内置的一些东西例如Promise,Set,Symbol等,就像使用无缝的使用polyfill,来使用babel 特性,并且无全局污染、极高代码库适用性。
虽然这种方法的优点是不会污染全局,但是,实例的方法,
Array.prototype.includes();
babel-polyfill
babel-polyfill则是通过改写全局prototype的方式实现,比较适合单独运行的项目。
开启babel-polyfill的方式,可以直接在代码中require,或者在webpack的entry中添加,也可以在babel的env中设置useBuildins为true来开启。
但是babel-polyfill会有近100K,
打包后代码冗余量比较大,
对于现代的浏览器,有些不需要polyfill,造成流量浪费
污染了全局对象
https://www.jianshu.com/p/7bc7b0fadfc2
这个加载器(loaders)还支持以下加载器特定选项:
-
cacheDirectory
:默认值false
。当设置时,给定的目录将用于缓存加载器的结果。未来的webpack构建将尝试从缓存中读取,以避免在每次运行时,需要运行 Babel 重新编译过程可能带来的高昂的开销。 如果值为空(loader: 'babel-loader?cacheDirectory'
)或true
(loader: babel-loader?cacheDirectory=true
),加载器将使用node_modules/.cache/babel-loader
中的默认缓存目录,或者如果在任何根目录中找不到node_modules
文件夹,加载器将使用默认的操作系统临时文件目录。 -
cacheIdentifier
:默认是由 babel-core 的版本组成的字符串,babel-loader 的版本,.babelrc文件的内容(如果存在)和环境变量BABEL_ENV
的值,并返回到NODE_ENV
环境变量。可以将其设置为自定义值,以在标识符更改时强制缓存无效。 -
babelrc
:默认true
。当为false
时,将忽略.babelrc
文件(除了extends
选项引用的那些文件)。 -
forceEnv
:默认将解析BABEL_ENV
,然后NODE_ENV
。允许您在加载器级别覆BABEL_ENV/NODE_ENV
。对于同构应用程序,在为客户端和服务器配置不同的babel时有用。
注意: sourceMap
选项被忽略,相反,当webpack配置为使用sourceMaps时,会自动启用它们(通过devtool
配置选项)。
10、loader
中!
代表的含义(从右到左)
{ test : /\.css\.less$/, loader : 'style!css!less' }
就代表了先使用less加载器来解释less文件,然后使用css加载器来解析less解析后的文件,依次类推
11、module.noParse(不被loaders解析的模块)
使用了noParse
的模块将不会被loaders
解析,所以当我们使用的库如果太大,并且其中不包含require
、define
或者类似的关键字的时候(因为这些模块加载并不会被解析,所以就会报错),我们就可以使用这项配置来提升性能。
例如下面的例子:在basic/
目录中新增no-parse.js
var cheerio = require('cheerio');
module.exports = function() {
console.log(cheerio);
}
webpack.config.js
中新增如下配置:
module : {
loaders : [
{ test : /\.js$/, loader : 'babel' },
{ test : /\.css$/, loader : 'style!css' }
],
noParse : /no-parse.js/
}
当执行打包后,在浏览器中打开index.html
时,就会报错require is not defined
noParse: [/moment-with-locales/]
module.noParse是webpack的另一个很有用的配置项,如果你 确定一个模块中没有其它新的依赖就可以配置这项,webpack将不再扫描这个文件中的依赖。
12、vendors(第三方包)
项目中用到了一些第三方库,如vue、vue-router、jquery、boostrap等。这些库我们基本上是不会改动源代码的,并且项目初期就基本确定了,不会再添加。所以把它们打包在一起。当然这个也是要考虑大小不超过500KB的,如果是用到了像ueditor这样的大型工具库,还是要单独打包的。
配置文件的写法是很简单的,在entry中配一个名为vendor的就好,比如:
entry: {
vendor: ['vue', 'vue-router', './public/vendor/jquery/jquery']
},
为了把第三方库拆分出来(用<script>标签单独加载),我们还需要用webpack的CommonsChunkPlugin插件来把它提取一下,这样他就不会与业务代码打包到一起了。代码:
plugins: [
new webpack.optimize.CommonsChunkPlugin('vendor');
]
- vendor的意思是依赖的第三方库,不会经常变更的,如你代码里的jQuery这种
- CommonsChunkPlugin是指被你重复引用的chunks。可能是vendor,也可能是你自己的某个公共组件
13、CommonsChunkPlugin
当你的 webpack 构建任务中有多个入口文件,而这些文件都 require 了相同的模块,如果你不做任何事情,webpack 会为每个入口文件引入一份相同的模块,显然这样做,会使得相同模块变化时,所有引入的 entry 都需要一次 rebuild,造成了性能的浪费,CommonsChunkPlugin 可以将相同的模块提取出来单独打包,进而减小 rebuild 时的性能消耗。
同时将多个入口文件相同的js打包处一个共同的后,也可以利用缓存,使加载第二页面的时候不需要再加载共同文件。
commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common', 'common.[hash].js');
CommonsChunkPlugin是内置在webpack里的,直接这样用即可:
const CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin
14、webpack的ProvidePlugin配置
原本是:
import $ from 'jquery';
才可以使用$
如果用providePlugin进行配置
- ProvidePlugin,是webpack的内置模块
- 以jquery为例,用ProvidePlugin进行实例初始化后,jquery就会被自动加载并导入对应的node模块中
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
_: 'lodash'
}),
15、process.env.NODE_ENV(环境变量)
"build-win": "SET NODE_ENV=production && webpack --config build/webpack.config.js"
16、resolve.alias
为模块设置别名,能够让开发者指定一些模块的引用路径。对一些经常要被import或者require的库,如react,我们最好可以直接指定它们的位置,这样webpack可以省下不少搜索硬盘的时间。
resolve: {
extensions: [‘.js‘, ‘.vue‘],
alias: {
‘@‘: path.resolve(__dirname, ‘src‘),
‘@scss‘: path.resolve(__dirname, ‘src‘, ‘scss‘),
}
}
// 原本这样写
import hongAlert from ‘./../src/scss/icon.scss‘
// 现在可以这样写
import hongAlert from ‘@scss/icon.scss‘
17、resolve.root和resolve.modulesDirectories
root是通过绝对路径的方式来定义查找模块的文件夹。可以是一个数组,主要是用来增加模块的搜寻位置使用的。
这里root的值必须是绝对路径,使用path.resolve设置。
var path = require('path');
// ...
resolve: {
root: [
path.resolve('./app/modules'),
path.resolve('./vendor/modules')
]
}
这样设置后,会增加搜索app/modules和vendor/modules下所有node_modules里面的模块。
modulesDirectories是用来设置搜索的目录名的,默认值:["web_modules", "node_modules"]。如果把值设置成["mydir"]
, webpack会查询 “./mydir”, “../mydir”, “../../mydir”等。
注意: Passing"../someDir","app","."or an absolute path isn’t necessary here. Just use a directory name, not a path. Use only if you expect to have a hierarchy within these folders. Otherwise you may want to use theresolve.root
option instead.
18、HotModuleReplacement(模块热替换)(插件)
new webpack.HotModuleReplacementPlugin() 不需要引入
改动了js,会自动编译刷新页面,能够方便开发。这是inline
参数的作用
假如一个项目很庞大,打包编译需要很长时间,那么通过HMR,就可以只替换必要的模块(修改过的模块),从而大大减少开发中等待编译的时间
19、devtool(调试工具)
开发总是离不开调试,方便的调试能极大的提高开发效率,不过有时候通过打包后的文件,你是不容易找到出错了的地方,对应的你写的代码的位置的,Source Maps
就是来帮我们解决这个问题的。
通过简单的配置,webpack
就可以在打包时为我们生成的source maps
,这为我们提供了一种对应编译文件和源文件的方法,使得编译后的代码可读性更高,也更容易调试。
source-map:在一个单独的文件中产生一个完整且功能完全的文件。这个文件具有最好的source map
,但是它会减慢打包速度;
cheap-module-source-map:在一个单独的文件中生成一个不带列映射的map
,不带列映射提高了打包速度,但是也使得浏览器开发者工具只能对应到具体的行,不能对应到具体的列(符号),会对调试造成不便;
eval-source-map:使用eval
打包源文件模块,在同一个文件中生成干净的完整的source map
。这个选项可以在不影响构建速度的前提下生成完整的sourcemap
,但是对打包后输出的JS文件的执行具有性能和安全的隐患。在开发阶段这是一个非常好的选项,在生产阶段则一定不要启用这个选项;
cheap-module-eval-source-map:这是在打包文件时最快的生成source map
的方法,生成的Source Map
会和打包后的JavaScript
文件同行显示,没有列映射,和eval-source-map
选项具有相似的缺点;
正如上表所述,上述选项由上到下打包速度越来越快,不过同时也具有越来越多的负面作用,较快的打包速度的后果就是对打包后的文件的的执行有一定影响。
对小到中型的项目中,eval-source-map
是一个很好的选项,再次强调你只应该开发阶段使用它
cheap-module-eval-source-map
方法构建速度更快,但是不利于调试,推荐在大型项目考虑时间成本时使用。
20、devServer:配置开发服务功能
npm install webpack-dev-server --save-dev
npm install webpack-cli -D
/*设置基本目录结构,也就是你想要使用服务的目录地址*/
contentBase:path.resolve(__dirname,'dist'),
/*服务器的IP地址,可以使用IP也可以使用localhost*/
host:'localhost',
/*服务端压缩是否开启,目前开不开都行,想关你就关*/
compress:true,
/*配置服务端口号,建议别用80,很容易被占用,你要是非要用也是可以的。*/
port:9090
21、less-loader
还有下载less
module: {
rules: [
{
test: /\.less$/,
use: [
'style-loader',
{ loader: 'css-loader', options: { importLoaders: 1 } },
'less-loader'
]
}
]
}