在自构建自己的个人页面的时候使用到webpack4,遇到了一些问题,查看了大佬们的文章以及官方文档,在这里总结一下。
webpack比较基础的东西就不赘述了,代码里面的注释也会辅助说明,先看一下目录结构:
│ .babelrc
│ .gitignore
│ package-lock.json
│ package.json
│ README.en.md
│ README.md
│
├─build
│ webpack.common.js
│ webpack.dev.js
│ webpack.prod.js
│ webpack.rules.js
│
└─src
├─assets
│ test.json
│
├─common
│ ├─css
│ ├─fonts
│ ├─images
│ └─js
└─pages
├─my
│ index.html
│ index.js
│ index.styl
│
└─other
index.html
index.js
index.styl
这里目录结构导出如果有不知道的同学,其实很简单,windows命令 tree /f 导出当前目录包括文件夹名字,tree /f > catalog.txt 导入到一个txt文本。
像大部分同学的习惯一样,在build文件夹里面分为几个webpack配置,common基础公用配置,dev开发环境配置,prod生产环境配置,以及单独分离出来的rule配置各项loader。
//common module.exports = (env) => { return { entry: {}, plugins: [], optimization: {}, module: {} } };
//dev
module.exports = merge(common(‘development‘), { mode: ‘development‘, devtool: ‘inline-source-map‘, output: {}, devServer: {}, plugins: [], });
//prod
module.exports = merge(common(‘production‘), { mode: ‘production‘, output: {}, plugins: [ ], });
这里webpack4 推荐用mode声明开发环境还是生产环境,这里是作为一个全局变量,而不是node环境,所以如果要在配置里面用到全局变量,用函数返回
这里我是直接定义的变量,然后在引用的时候传入参数,不是官方所定义的全局变量,其实这样写不是很好,既然分离了环境那就应该在不同的配置文件中写配置。
webpack里面的entry
entry: { // 多入口文件 my: [ ‘./src/pages/my/index.js‘, ], other: [ ‘./src/pages/other/index.js‘, ] },
在外部定义多个页面的信息,以及html-webpack-plugin模版插件的函数进行批量操作
/*可多页面配置*/ const htmlArray = [ { _html: ‘my‘, title: ‘我的首页‘, // chunks: [‘my‘] }, { _html: ‘other‘, title: ‘其他‘, // chunks: [‘other‘] } ]; // 获取html-webpack-plugin参数的方法 let getHtmlConfig = function (name, title, globalEnv) { return { template: `./src/pages/${name}/index.html`, filename: `${name}.html`, // favicon: ‘./favicon.ico‘, title: title, inject: true, hash: false, //开启hash ?[hash] /*chunk 里面配置的文件才会在html中引入,所以有其他引入的话要注意加上, 比如runtime和splitChunks里面的vendor等,建议不要这个,默认加载所有的*/ // chunks: chunks, minify: globalEnv === "development" ? false : { removeComments: true, //移除HTML中的注释 collapseWhitespace: true, //折叠空白区域 也就是压缩代码 removeAttributeQuotes: true, //去除属性引用 }, }; };
在webpack plugin里面引入执行html模版
//自动生成html模板 ...htmlArray.map((element) => { return new HtmlWebpackPlugin(getHtmlConfig(element._html, element.title, env)); }),
由于loader比较多,可以单独提取到一个配置文件
css,css预处理器loader,MiniCssExtractPlugin是webpack4分离css的插件,后面再提到
{ test: /\.(css|styl)$/, // 区别开发环境和生成环境 /*用了MiniCssExtractPlugin,不要用style-loader,冲突*/ use: env === "development" ? ["style-loader", "css-loader", "stylus-loader"] : [MiniCssExtractPlugin.loader, "css-loader", "stylus-loader"] },
{ test: /\.js$/, exclude: "/node_modules/", use: [{ loader: "babel-loader", options: { /*可使用禁止在每个文件注入runtime,避免文件多而大,采用babel-plugin-transform-runtime辅助提取引用 * plugins: [‘@babel/transform-runtime‘]*/ // 配置在 .babelrc 中,和browserslist // presets: [‘@babel/preset-env‘] } }] },
这里是base64转换和输入位置,更多配置可以看官网
{ test: /\.(png|jpg|gif)$/, use: [{ // url-loader包含file-loader loader: "url-loader", options: { limit: 5 * 1024, //小于5k时将会已base64位图片打包处理 // 图片文件输出的文件夹 outputPath: "images" } }] },
字体和html的 loader
{ test: /\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/, loader: ‘url-loader‘, options: { limit: 10000, /*原来的名字和后缀*/ name: ‘[name].[ext]‘, // 文件输出的文件夹 outputPath: "fonts" } }, { test: /\.html$/, // html中的img标签 use: ["html-withimg-loader"] },
common 里面,第一个是html模版,上面讲过了,第二三个顾名思义。
plugins: [ //自动生成html模板 ...htmlArray.map((element) => { return new HtmlWebpackPlugin(getHtmlConfig(element._html, element.title, env)); }), // 消除冗余的css代码 new PurifyCssWebpack({ paths: glob.sync(path.join(__dirname, "../src/pages/*/*.html")) }), //静态资源输出 new CopyWebpackPlugin([{ from: path.resolve(__dirname, "../src/assets"), to: ‘./assets‘, ignore: [‘.*‘] }]), ],
dev,这里官方提示使用这里完全启发devServer热更新,我没深入研究,同志们可以研究一下。
plugins: [ //热更新,配合devserver服务完全启动HMR new webpack.HotModuleReplacementPlugin(), // new BundleAnalyzerPlugin(), //性能优化 高大上的可视化分析模块 ],
prod,清理dist的插件有一点小变动,提取css的插件官方建议被替代,以及仍然需要额外的插件压缩css
plugins: [ /*删除dist目录,2.0后默认了output的path,这里无需填写*/ new CleanWebpackPlugin({ root: path.resolve(__dirname, ‘../‘), //根目录 // verbose Write logs to console. verbose: true, //开启在控制台输出信息 }), /*webpack用这个代替ExtractTextPlugin,提取,开发环境我没分离*/ new MiniCssExtractPlugin({ // Options similar to the same options in webpackOptions.output // both options are optional filename: ‘[name].[contenthash].css‘, // chunkFilename: ‘[id].[contenthash].css‘, }), //压缩css new OptimizeCSSPlugin(), ],
/*代码分离 压缩,webpack4x集成部分插件和选项*/ optimization: { /*压缩js代码入口,是否开启minimizer, 例如TerserWebpackPlugin插件,性能比UglifyJSPlugin好 默认引入生产模式为true,所以不用操作,可以手动开启和调节minimizer选项*/ // minimize: false /*将运行时代码拆分为单独的块。 将其设置single为为所有块创建单个运行时包 单页面 runtimeChunk: ‘single‘, */ /*多页面别名*/ runtimeChunk: { name: entryPoint => `runtimechunk~${entryPoint.name}` }, /*分离公共代码*/ splitChunks: { /*缓存chunk 提取公共模块复用*/ cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name: ‘vendors‘, chunks: ‘all‘ } } }, },
devServer: { contentBase: path.join(__dirname, "../dist"), publicPath:‘/‘, host: "127.0.0.1", port: "5199", overlay: true, // 浏览器页面上显示错误 // open: true, // 开启浏览器 open: ‘Google Chrome‘ // stats: "errors-only", //stats: "errors-only"表示只打印错误: hot: true, // 开启热更新 // compress: true, //开启gzip },
output: { path: path.resolve(__dirname, ‘../dist‘), // 打包多出口文件 // 生成 a.bundle.[hash].js b.bundle.[hash].js // hash工程级整个是一样的,chunkhash模块级有依赖的文件是一样的,contenthash根据自身的内容生成hash,每个文件都不一样 filename: ‘./js/[name].[contenthash].js‘, publicPath: ‘./‘ },
开发依赖
"@babel/cli": "^7.2.3",
"@babel/core": "^7.3.4",
"@babel/plugin-transform-runtime": "^7.3.4",
"@babel/preset-env": "^7.3.4",
"babel-loader": "^8.0.5",
生产也需要的依赖
"dependencies": {
"@babel/polyfill": "^7.2.5",
"@babel/runtime": "^7.3.4"
}
其中runtime官方的说法是节约代码以及生成器语法的转换,如果不用这两个使用async和await会报错。
然后在.babelrc中使用,关于 @babel/polyfill 的使用,这里配合 @babel/preset-env 有三种使用方式,这里usage会自动根据代码转换,安装后不要引入。
{ "presets": [ [ "@babel/preset-env", { "useBuiltIns": "usage" } ] ], "plugins": [ "@babel/plugin-transform-runtime" ] }
最后在package.json或者单独建立browserslist文件来限制浏览器版本和转换操作
"browserslist": [
"defaults",
"not ie < 11",
"last 2 versions",
"> 1%",
"iOS 7",
"last 3 iOS versions"
],
最后启动和大概测试了下,没发现什么问题。
由于时间和能力有限,可能有很多没考虑到,不够深入理解,还有一些冗余甚至错误的地方望各位大佬指正。
参考:
1,多页面配置,参考的是这位大佬的文章。https://segmentfault.com/a/1190000014984842
2,webpack官方文档,可以统一看一遍。https://webpack.js.org/plugins/mini-css-extract-plugin/
3,babel相关官方文档 https://babeljs.io/docs/en/babel-polyfill#docsNav
附:
1,在线配置webpack的页面,常用的依赖,插件和代码分割以及安装命令等。https://webpack.jakoblind.no/
time:2019-02-15
原文:https://www.cnblogs.com/caelan/p/10527635.html