webpack简介:
webpack是前端资源加载/打包工具,它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。在做vue项目和react项目时都会可能用到,当前最火的前端构建工具之一,把前端各种资源编译打包,最后输出:js文件、css文件、png文件,可以减少文件资源的请求。
编译原理:利用各种处理文件的loader对各种文件进行编译,根据文件后缀处理后输出新的文件,如需了解更多建议阅读相关文档:https://webpack.docschina.org/
特别强调:webpack配置文件命名为:webpack.config.js
基本使用步骤如下:
1.在命令行键入以下命令回车创建项目文件夹,也可以通过鼠标右键创建项目文件夹(命名随意):
mkdir webpackproject
2.在webpackproject文件夹中初始化一个package.json文件:
npm init -y
3.下载安装webpack及webpack-cli,命令行输入以下命令后回车:
npm install webpack webpack-cli --save-dev
4.更新目录结构:
webpackproject
|- package.json
|- index.html
|- /src //此目录存放开发环境代码
|- index.js//在此文件中键入测试代码:document.write('hello');
5.新建一个dist文件夹并将index.html文件复制到此文件夹中,如:
webpackproject
|- package.json
|- /dist //此目录用于存放生产环境代码,也就是要上线的代码
|- index.html
|- /src
|- index.js
6.在命令行执行以下命令回车,此时会发现dist文件夹中新增main.js文件,此文件就是src下面的index.js文件压缩版(以后在修改完src中的代码后再执行此命令,dist中的代码会自动更新):
webpack 或 npx webpack --config webpack.config.js
此方式不是很方便,可以在package.json文件中配置一个快捷启动方式:在scripts键中添加:“build”: “webpack”,这里的build可以是任意没有意义的值,之后启动时在命令行输入:npm run build即可,build 需要保持一致。
7.使用webpack配置文件:有的项目中会用到webpack配置文件,这比直接在终端输入命令高效的多,基本配置如下:
// webpack文件主配置:
module.exports = {
mode: 'production', //启用webpack内部在相应环境下的优化,其值还有:development和none,实际是控制dist文件夹下文件是否压缩。
entry: { //---entry配置入口文件,指示 webpack 使用哪个模块来作为构建的基础;也可以是多入口来创建多页面应用程序,这里介绍单页面应用程序;
main: './src/main.js', //---main是默认入口,即veu项目中的main.js文件,main.js文件用来监听index.html文件中的盒子,并将app.vue文件的渲染结果返回给index.html文件中的这个盒子。
vendor: './src/vendor.js' //第三方库,会将main.js和vendor.js文件分开,这里可以不用配置此项。
}, //entry后面还可以直接跟字符串路径或数组路径,如:entry: './src/main.js'和entry: ['./src/file1.js', './src/file2.js']
output: { //---文件出口,将打包好的文件命名后输出
filename: './build.js', //---指定最终生成的js文件名
path: path.join(__dirname, 'dist') //----打包好的文件路径,最好是绝对路径;这里代表当前目录的上一级的dist目录;注意引入path模块
},
module: {
rules: [ //------webpack默认只能认识javascript和json文件,更多的loader可以用于配置处理更多的一类文件,此配置为loader配置,这里可以用更早的loaders:[],功能和rules一样,不推荐;需要注意这些lodaer需要install且有的有依赖也要install。
{ //test是用于检测文件类型的;use是指定使用哪个loader,更早版本可以使用loader代替use但是不推荐。
test: /\.css$/, //-----处理css文件需要引入多个loader,如style-loader和css-loader中间可用!分开,test用于检测文件后缀
use: 'style-loader!css-loader' //-----这里是有顺序的,不能反过来使用;use还可以接数组,数组的每一项配置对应的loader如:
// use: [
// { loader: 'style-loader' },
// {
// loader: 'css-loader',
// options: {
// modules: true
// }
// }
// ]
},
{
test: /\.(jpg|svg|png|gif)$/, //----url-loader?limit=4096$name=[name].[ext]处理后缀为jpg、svg的图片文件,这里可以处理很多种格式的图片文件,只需要将文件后缀配置到这里即可。
use: 'url-loader?limit=4096$name=[name].[ext]', //[name].[ext]内置提供,[name]用来设置文件名,[ext]用于设置文件后缀名;limit用于设置当文件大于某字节时以base64格式输出,问号后面可以以options方式输出(废弃,不推荐),(新版中采用file-loader)如:
//options方式输出配置,已经废弃:
//options:{
// limit:4096,
// name:[name].[ext]
//}
},
{
test: /\.js$/, //----bable-loader处理后缀为js的文件
use: 'babel-loader',
exclude: /node-modules/, //---排除某文件下的文件不被处理,这里一般排除第三方资源,如node-modules文件夹中的文件
options: {//注意废弃问题
presets: ['es2015'], //关键字,这里配置的是解析es6语法
plugins: ['transform-runtime'], //函数
}
},
{
text: /\.vue$/, //解析vue文件配置:
use: 'vue-loader' //vue-template-compiler是代码上的依赖
},
{
test: /\.txt$/,
use: 'raw-loader'
}
]
},
plugins: [ //配置插件,执行范围更广的任务,如:打包优化,资源管理,注入环境变量。
new htmlWebpackPlugin({ //将src下的template属性描述的文件移动到当前output.path的配置目录下并生成html文件,htmlWebpackPlugin是一个模块,需要引入:html-webpack-plugin模块(应用程序生成一个 HTML 文件,并自动注入所有生成的 bundle)
template: './src/index.html'
})
]
};
//下面是新版webpack基本的webpack.ocnfig.js文件代码:
const htmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path')
module.exports = {
mode: 'production',
entry: {
main: './src/main.js',
vendor: './src/vendor.js'
},
output: {
filename: './build.js',
path: path.join(__dirname, 'dist')
},
module: {
rules: [{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.(jpg|svg|png|gif)$/,
use: ['file-loader']
},
{
test: /\.js$/,
use: 'babel-loader',
exclude: /node-modules/
// options: {
// presets: ['es2015'],
// plugins: ['transform-runtime'],
// }
},
{
text: /\.vue$/,
use: 'vue-loader'
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
'file-loader'
]
},
{
test: /\.txt$/,
use: 'raw-loader'
},
{
test: /\.(csv|tsv)$/,
use: [
'csv-loader'
]
},
{
test: /\.xml$/,
use: [
'xml-loader'
]
}
]
},
plugins: [
new htmlWebpackPlugin({
template: './src/index.html'
})
]
};
如果配置完此文件,在命令行直接键入npm run build等启动命令,则会自动生成dist文件夹及里面文件,这样在做一个项目的时候就快捷多了,同时也会处理更多不同格式的文件(利用不同的loader)。
常见处理各种资源的loader总结:
在javascript模块中引入其他文件,需要安装对应的loader,之后在将这些loader配置到对应的位置,如:
资源 | loader及描述 |
---|---|
css文件 | style-loader 和 css-loader;用于解析通过import导入js文件的css文件等 |
images图像 | file-loader;解析background和icon等图像文件 |
fonts字体 | file-loader 和 url-loader 可以接收并加载任何文件,这里采用其中一种就可以解析fonts文件 |
数据文件 | csv-loader和xml-loader解析json、xml等数据 |
vue文件 | vue-loader,处理vue组件 |
html-webpack-plugin:
用于生成一个HTML5文件并将这个文件打包到dist目录下的插件,使用时只需要将其添加到webpack配置文件中(使用过此插件后dist文件夹中生成的index.html文件会引用dist文件下的main.js文件,此main.js文件会包含css等),如:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');//需要安装
module.exports = {
entry: {
app: './src/index.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new HtmlWebpackPlugin({
title: 'index'
})
],
};
clean-webpack-plugin:
用于清除dist目录中的旧文件,在每次构建时都会清除之前构建的dist目录下的文件,这样dist文件夹就不会显得很杂乱了,如:
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin'); //注意需要安装
module.exports = {
entry: {
app: './src/index.js',
print: './src/print.js'
},
plugins: [
new CleanWebpackPlugin()
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
source map:
在开发环节中,webpack会将不同的模块最终打包到一起,此时如果某个模块有错误,这个错误只会显示在打包后的总文件中,此时想要修改未打包前的原文件,那么就很难找到错误所在了。当然webpack提供了source map可以将编译好的代码映射到源码中,这样就可以找到错误所在了,具体如:
module.exports = {
mode: 'development', //1.将mode设置为开发环境
entry: {
app: './src/index.js'
},
devtool: 'inline-source-map', //2.devtool属性设置为inline-source-map
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist')
}
};
//3.此时如果某个文件有错误,那么在控制台就会清楚的显示到某文件某行出现错误。
自动编译:
webpack提供了几种自动编译代码的配置,当代码被修改后会自动编译,此配置有:webpack watch mode(webpack 观察模式)、webpack-dev-server、webpack-dev-middleware,常用webpack-dev-server,它们具体使用方法如下:
webpack watch mode:(缺点:浏览器不能被自动刷新)
1.在package.json文件scripts中添加:"watch": "webpack --watch"
2.在终端输入:npm run watch
3.不要关闭终端,当文件发生修改并保存后,在终端就会看到文件被修改了
webpack-dev-server:
1.npm install --save-dev webpack-dev-server 终端下载并安装
2.在webpack.config.js文件module.exports中添加如下代码,表示搜索栏输入搜索后从什么位置查找文件:
devServer: {
contentBase: './dist'
}
3.此时当代码发生修改在浏览器端就可以实现修改效果,但是输出文件是不会被修改的,若想要输出的文件也被修改,那么就要在package.json文件scripts中添加:"start": "webpack-dev-server --open"
4.在终端输入:npm start ,代码被编译并重新加载到浏览器
webpack-dev-middleware:它是一个封装器,可以将webpack处理过的文件发送到服务器,比较繁琐,不推荐使用。
1.npm install --save-dev webpack-dev-middleware 终端下载安装
2.webpack.config.js文件output中添加:publicPath: '/' 来确保middleware中间件能被启动
3.在服务端脚本使用 publicPath 使文件资源能被浏览器访问到
4.在服务端脚本use中间件:webpackDevMiddleware,如下:
app.use(webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath
}));
5.在package.json文件scripts中添加:"server": "node server.js"
6.在终端输入:npm run server 后在浏览器访问指定地址,就会看到webpack运行。
注意:在开启自动编译代码后,有的编辑器会有安全写入配置,此功能会影响自动编译,此时需要将这个编辑器的此功能禁用掉,不同的编辑器方法不同,建议百度。
HMR模块热替换:
允许在运行时不完全刷新而更新所有类型模块,可以提高开发效率,其具体使用如下(这里采用webpack-dev-server作为基础):
1.const webpack = require('webpack'); 引入webpack自身来使用内置模块
2.在webpack.config.js文件中配置:devServer对象中添加:hot: true ;plugins对象中添加:new webpack.HotModuleReplacementPlugin()
3.在index.js打包后的文件中输入:
if (module.hot) {
module.hot.accept('./print.js', function() {
printMe();
})
}
webpack-merge分离配置webpack.config.js:
实际中会将开发环境和生产环境的webpack文件分离开,但是他们有着相同的部分,此时可以将webpack配置文件分离开,在不同的配置文件引入相同的部分配置文件即可,具体如:
//1.npm install --save-dev webpack-merge 下载安装webpack-merge
//2.在webpackproject项目文件夹下,新建若干webpack配置文件,并将之前的 webpack.config.js删除:
//|- webpack.common.js //用于写公共配置的文件,配置entry、output、plugins等,如:
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
app: './src/index.js'
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Production'
})
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
|- webpack.dev.js //用于写开发环境的配置文件,需要引入common配置文件和webpack-merge模块,如:
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
devServer: {
contentBase: './dist'
}
});
|- webpack.prod.js //用于写生产环境的配置文件,需要引入common配置文件和webpack-merge模块,如:
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production',
});
//3.将package.json文件scripts中的配置修改为启动上面分离开的webpack配置文件,在终端只需npn 对应配置 即可启动指定webpack配置,如:
"scripts": {
"start": "webpack-dev-server --open --config webpack.dev.js", //通过npm start启动webpack.dev.js
"build": "webpack --config webpack.prod.js" //通过npm build启动webpack.prod.js
}
代码分离:
此特性能够把代码分离到不同的 bundle 中,按需加载,可以提高效率;常见的代码分离有三种方式:入口起点、防止重复、动态导入,下面将简单介绍一下:
//1.入口起点(不推荐):说白了就是在entry中配置多个入口,优点是比较简单直观,缺点是比较繁琐,需要手动配置且存在隐患,如:
module.exports = {
entry: {
index: './src/index.js',
another: './src/another.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};//此时从新构建会生成多个js文件在dist文件夹中,但是会将重复的模块引入到各个bundle中,且不能动态的将核心应用程序逻辑代码拆封开。
//2.防止重复(不推荐):SplitChunksPlugin插件可以将公共的依赖模块提取到同一个chunk中,这样就可以去重;其配置是在入口起点的方式上加上以下配置:
module.exports = {
entry: {
index: './src/index.js',
another: './src/another.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
// 新添加的配置代码:
optimization: {
splitChunks: {
chunks: 'all'
}
}
};//此时重新构建会将重复的依赖删除,webpack提供了mini-css-extract-plugin(将CSS从主程序中分离)、bundle-loader(分离代码和延迟加载生成的bundle)、promise-loader(使用了promise API,类似bundle-loader)
//3.动态导入(推荐):动态拆封代码时,webpack提供了动态导入,具体如下:
module.exports = {
entry: {
index: './src/index.js',
},
output: {
filename: '[name].bundle.js',
chunkFilename: '[name].bundle.js',//配置chunkFilename
path: path.resolve(__dirname, 'dist')
}
};//此时就可以通过一个入口分离,且不会重复;
预加载和预取:
webpack提供了预加载相关指令,在声明 import 时,使用内置的这些指令:prefetch(预取),将来某些导航下可能需要的资源、preload(预加载),当前导航下可能需要资源,其用法如下:
import(/* webpackPrefetch: true */ 'LoginModal'); //会生成 并追加到页面头部,指示着浏览器在闲置时间预取 login-modal-chunk.js 文件。
import(/* webpackPreload: true */ 'ChartingLibrary');//在请求 ChartComponent.js 的同时,还会通过 请求 charting-library-chunk。
懒加载:
懒加载或按需加载是优化网页很好的功能,这里只介绍相关框架的懒加载内库:
React: https://reactrouter.com/web/guides/code-splitting
Vue:https://alexjover.com/blog/lazy-load-in-vue-using-webpack-s-code-splitting/
AngularJS: 百度查
缓存:
通过缓存,可以降低网络流量,使网站加载速度更快,然而当修改完代码后,文件名没有修改的情况下,浏览器会认为没有修改,此时更新的代码就不会被利用,而是继续使用的缓存文件;当然webpack解决了这一问题:简单的配置就能使被webpack编译的新文件被缓存并可以请求到新文件,其原理是利用动态设置文件名而解决缓存问题的,如:
module.exports = {
entry: './src/index.js',
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'test'
})
],
output: {
filename: '[name].[contenthash].js', //动态生成文件名的方式来解决缓存问题
path: path.resolve(__dirname, 'dist')
}
};
提取索引模板:
webpack 提供一个优化功能代码分离的功能,可使用 optimization.runtimeChunk 选项将 runtime 代码拆分为一个单独的 chunk。将其设置为 single 来为所有 chunk 创建一个 runtime bundle,其配置如下:
module.exports = {
entry: './src/index.js',
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({ title: 'Caching' })
],
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist')
},
optimization: {
runtimeChunk: 'single' //配置runtimeChunk: 'single'
}
};
实际中会将第三方的包也分离开,这样可以避免第三方包的频繁修改,减少请求,其配置如:
module.exports = {
entry: './src/index.js',
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({ title: 'Caching' })
],
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist')
},
optimization: {
runtimeChunk: 'single', //配置runtimeChunk: 'single'
splitChunks: { //继续配置此项实现分离第三方包
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
}
};
模块标识符:
模块标识符是用来解决vendor bundle不被修改的功能,使用此功能需要配置如下配置:
const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Caching'
}),
new webpack.HashedModuleIdsPlugin() //配置项
],
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist')
},
optimization: {
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
}
};
创建library:
可以将自己开发的包进行打包,其基本用法如:
//1. npm init -y 终端初始化一个项目文件夹
//2. npm install --save-dev webpack lodash 终端下载安装webpack和lodash
//3. 编写自己的包
//4. webpack.config.js基本配置:
var path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'webpack-name.js'//自定义name值
library: 'webpackName'
},
externals: {
lodash: {
commonjs: 'lodash',
commonjs2: 'lodash',
amd: 'lodash',
root: '_'
}
}
};
//5.将包添加到package.json文件main字段,如:
"main": "dist/webpack-numbers.js"
预设依赖shim:
webpack默认是无法识别一些第三方库的全局依赖或变量,但是shim可以解决这一问题,具体如:
//shim预设全局变量:想要将模块依赖改为全局变量依赖就要用到 ProvidePlugin 插件,如:
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new webpack.ProvidePlugin({
_: 'lodash'//告诉webpack如果用到以_变量的模块,将lodash package引入
//join: ['lodash', 'join'] //暴露模块单个导出
})
]
};
//细粒度shim:指的是一些依赖的this指向window对象,而在commonjs中此时this指向module.exports,为了this指向window,可以配置如下:
module: {
rules: [{
test: require.resolve('index.js'),
use: 'imports-loader?this=>window' //配置后将原本指向module.exports的this重新指向为window
}]
}
//全局export:将全局变量作为一个普通模块导出,利用exports-loader,如:
module: {
rules: [{
test: require.resolve('index.js'),
use: 'imports-loader?this=>window'
},
{
test: require.resolve('globals.js'),
use: 'exports-loader?file,parse=helpers.parse'
}
]
}
//加载 polyfill:可以使用原生功能,配置如下:
//1.npm install --save babel-polyfill 下载安装babel-polyfill
//2.使用import将babel-polyfill导入src/index.js文件
//3.npm install --save whatwg-fetch 继续下载安装whatwg-fetch
//4.import 'babel-polyfill';import 'whatwg-fetch' 到src/polyfills.js文件,并将src/index.js文件中babel-polyfill去掉
//5.在webpack.config.js文件中新增入口 polyfills: './src/polyfills.js';新增动态输入文件名:filename: '[name].bundle.js'
//6.此时可以在dist/index.html文件head标签中新增一下逻辑就可以根据以下逻辑来加载polyfill
<script>
var modernBrowser = (
'fetch' in window &&
'assign' in Object
);
if (!modernBrowser) {
var scriptElement = document.createElement('script');
scriptElement.async = false;
scriptElement.src = '/polyfills.bundle.js';
document.head.appendChild(scriptElement);
}
</script>
渐进式网络应用程序:
一种在离线环境下继续运行的功能,类似于native app,其原理是通过Service Workers 的 web 技术来实现。其具体用法如下:
//1.npm install http-server --save-dev 安装http-server
//2.修改package.json文件scripts中配置为:"build": "webpack"和"start": "http-server dist"
//3.终端输入:npm run build 构建项目、npm start 启动服务,此时在停止服务的情况下是无法做到离线运行的,想要做到离线运行,就得继续下一步:
//4.npm install workbox-webpack-plugin --save-dev 安装workbox-webpack-plugin,并在webpack.config.js文件中引入:const WorkboxPlugin = require('workbox-webpack-plugin');
//5.配置webpack.config.js文件中plugins项如下:
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({}),
new WorkboxPlugin.GenerateSW({//开启离线可运行配置
clientsClaim: true,
skipWaiting: true
})
]
//6.终端继续输入:npm run build 可以看到新增:service-worker.js和precache-manifest.b5ca1c555e832d6fbf946fd29d27eb.js文件,则表示Service Worker创建成功
//7.在index.js文件总添加如下代码用以注册Service Worker:
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js').then(registration => {
console.log('SW registered: ', registration);
}).catch(registrationError => {
console.log('SW registration failed: ', registrationError);
});
});
}
//8.在此运行 npm run build 构建项目,之后在运行 npm start 启动项目。
//9.到浏览器通过http://localhost:8080访问并查看控制台console是否存在:SW registered,存在则表示成功
//10.停止server进行测试,如果浏览器支持Service Worker则可以看到程序运行正常。
处理TypeScript:
TypeScript 是 JavaScript 的超集,增加了类型系统,可以编译为 JavaScript 代码。下面将介绍如何将 webpack 和 TypeScript 进行集成,其基础配置如下:
//1.npm install --save-dev typescript ts-loader 下载安装typescript和ts-loader
//2.在某个项目文件夹中新增:tsconfig.json配置文件,其配置如下:
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,//用以开启source map
"noImplicitAny": true,
"module": "es6",
"target": "es5",
"jsx": "react",
"allowJs": true
}
}//这里只是简单配置,如果想要了解更多关于tsconfig.json配置,可阅读:https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
//3.在webpack.config.js文件rules中新增处理ts的配置如下:
module.exports = {
entry: './src/index.ts',//入口ts文件并处理里面依赖的ts和tsx文件,处理后输出到:bundle.js文件中
devtool: 'inline-source-map',//配置source map
module: {
rules: [{
test: /\.tsx?$/, //处理ts
use: 'ts-loader',
exclude: /node_modules/
}]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
在使用typescript时,可能会引用第三方library,此时需要安装对应第三方library,如typescript中lodash为:@types/lodash,需要安装的则为:npm install --save-dev @types/lodash;更多配置查阅:https://devblogs.microsoft.com/typescript/the-future-of-declaration-files-2/
typescript中导入其他资源:
在 TypeScript 中使其他资源,需要告知TypeScript导入资源类型,具体做法如下:
//1.在项目中创建一个custom.d.ts文件(用于自定义类型声明),如配置.svg文件配置如下:
declare module "*.svg" {
const content: any;
export default content;
}//配置其他CSS, SCSS, JSON 资源方法类似。
环境变量:
开发环境和生产环境之间的webpack.config.js存在差异,通过环境变量就可以消除差异。在webpack命令行中配置环境变量用到–env,配置好的环境变量可以在webpack.config.js文件中被访问到,如:
//配置环境变量:
webpack --env.number = '2'
//接收环境变量:
module.exports = env => {
console.log(env.number);
}
构建性能:
无论在开发环境还是生产环境,都应给提高构建性能以达到最佳效果。性能优化可以从以下几点出发:
1.更新webpack及node.js、npm等到最新版本,新版本中可以提高解析速度。
2.仅对必要的模块使用loader,使用include将loader应用在实际需要转换的模块所指路径,如:
rules: [{
test: /\.js$/,
include: path.resolve(__dirname, 'src'),
loader: 'babel-loader'
}]
3.loader或plugin都有自己的启动时间,尽量少用。
4.从解析角度出发减少文件系统调用次数、关闭不用的resolve.symlinks、
5.使用 DllPlugin将更改不频繁的代码单独编译
6.减小编译结果的整体大小
7.通过thread-loader将非常耗资源的loader分给一个worker pool
8.通cache-loader启动持久化缓存;使用package.json中"postinstall" 清除缓存目录
9.增量编译:使用 webpack 的 watch mode;使用 watchOptions.poll 来增加轮询的间隔
10.在内存中编译:webpack-dev-server、webpack-hot-middleware、ebpack-dev-middleware
11.小化每个增量构建步骤中,从 stats 对象获取的数据量
12.某些工具只能在生产环境才会有作用,尽量避免在开发环境使用这类工具:TerserPlugin、[hash]/[chunkhash]、AggressiveMergingPlugin等
13.最小化 entry chunk
14.避免额外的优化步骤
15.输出结果不携带路径信息
16.使用TypeScript loader内置watch mode API
17.尽量少使用source map
18.还有很多做优化的方面,这里不再做过多介绍。
内容安全策略:
webpack 能够为其加载的所有脚本添加 nonce,启用此功能需在入口文件配置__webpack_nonce__变量,且应该为每个页面视图添加唯一的hash的nonce,`、nonce 应该是一个 base64 编码的字符串。
开发 - Vagrant:
使用Vagrant在虚拟机上运行开发环境且运行webpack,步骤如下:
1.确保 Vagrantfile 拥有一个静态 IP
Vagrant.configure("2") do |config|
config.vm.network :private_network, ip: "10.10.10.61"
end
2.项目中安装 webpack 和 webpack-dev-server:
npm install --save-dev webpack webpack-dev-server
3.确保有webpack.config.js 配置文件,配置代码如:
module.exports = {
context: __dirname,
entry: './app.js'
};
4.确保有一个index.html文件,且有一script标签(src指向你的bundle)
5.创建一个app.js文件
6.webpack-dev-server --host 0.0.0.0 --public 10.10.10.61:8080 --watch-poll 启动server
配合 nginx 的高级用法:
为更好模拟类生产环境,可采用nginx代理webpack-dev-server,nginx配置如下:
server {
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
error_page 502 @start-webpack-dev-server;
}
location @start-webpack-dev-server {
default_type text/plain;
return 502 "Please start the webpack-dev-server first.";
}
}
webpack-dev-server 启动命令可修改为:webpack-dev-server --public 10.10.10.61 --watch-poll
提示:本文图片等素材来源于网络,若有侵权,请发邮件至邮箱:[email protected]联系笔者删除。
笔者:苦海