一张图带你了解webpack的requirecontext

很多人应该像我一样,对于webpack的require.context都是一知半解吧。网上很多关于require.context的使用案例,但是我没找到可以帮助我理解这个知识点的,于是也决定自己来探索一下,下面以网上流行的svg图标方案为例说明。对了,本文的重点是require.context,并不会去解释svg symbol方案svg-sprite-loader。 关键代码 src/icons/index.js const context = require.context("./svg", true, /\.svg$/)context.keys().map(context)main.js import '@/icons'webpack.base.config.js { test: /\.svg$/, loader: "svg-sprite-loader", include: [resolve("src/icons")], options: { symbolId: "icon-[name]" }},{ test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: "url-loader", exclude: [resolve("src/icons")], options: { limit: 10000, name: utils.assetsPath("img/[name].[hash:7].[ext]") }},why? 很多人跟我一样,一开始只想说,为什么这样就可以,why??? 要知道是什么,就上打印大法。 const context = require.context("./svg", true, /\.svg$/)// 看看你是何方神圣console.log(context)context.keys().map(context)下面就真的以一张图进行解释,有问题的欢迎留言交流呀! 首发链接

July 10, 2019 · 1 min · jiezi

如何解决npm-run-build后页面空白

欢迎关注前端小讴的github,阅读更多原创技术文章问题一:assetsPublicPath配置错误解决办法:打开config/index.js文件 build:{ // assetsPublicPath: '/' assetsPublicPath: './'} 问题二:路由history模式配置有误解决办法:关闭路由historym模式 export default new Router({ // mode: 'history', // require service support scrollBehavior: () => ({ y: 0 }), routes: constantRouterMap})

July 10, 2019 · 1 min · jiezi

webpack-基础loader实现

webpack loader 学习初识loader webpack入门基本都看过它,webpack最主要的功能就是把蓝色菱形左边各式各样的模块全部打包成右边这几种统一规范的文件,而核心蓝色菱形就是loader。 举几个小例子: vue 文件 需要用到vue-loaderes6 语法 需要使用babel-lodersass 样式文件 需要用到sass-loader...loader是什么本质上来说loader是一个node模块是文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译、压缩等,最终一起打包到指定的文件中loader支持链式调用,依次调用,同一种文件支持多个loader自下而上执行loader基本使用 这是一个webpack.base.confi.js的module配置,一些文件所需要的loader一般写在module.rules中。test定义的是正则匹配文件类型,loader是定义编译此文件所需要的loader工具名,options、include都是一些相关配置文件,这里不做赘述。 实现一个非常简单的loader从零开始新建一个文件夹loader-study npm initwebpack initnpm install 来创建一个简单的打包工具。在webpack init过程中遇到加入css babel这样的loader的时候都可以选择否,我们实现的重点不在这块。 下面贴一下webpack.config.js的代码,都是些webpack基本配置,重点是module.rules里面的loader配置,我们这次要实现的是一个解析txt文件的loader,命名为self-loader. const path = require('path'); var HtmlWebpackPlugin = require('html-webpack-plugin') const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); module.exports = { entry: { app: './app.js' }, output: { filename: 'result.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { // 这个loader是我们自己实现的loader test: /\.txt$/, loader: 'self-loader' } ] }, plugins: [new UglifyJSPlugin(), new HtmlWebpackPlugin({ template: './index.html', filename: './output.html' })] };接下来你需要在node_modules文件夹中创建一个self-loader 文件夹并在此文件夹下创建一个index.js。先上代码等下解释。 ...

July 10, 2019 · 1 min · jiezi

Vue-Webpack-重写cookie路径

webpack提供的反向代理服务器在开发阶段非常方便,几行简单的代码配置就可以使用反向代理功能,包括路径重写、cookie处理等。 项目开发阶段使用的API路径是 /admin,部署到线上是/,所以在开发过程中需要在proxyTable进行反向代理配置,将路径重写掉,路径重写代码如下(config/index.js): proxyTable: { '/admin': { target: 'http://127.0.0.1:8080', changeOrigin: true, pathRewrite: { '^/admin': '/admin2' }, }}启动项目之后进行登录,此时API请求成功,但是获取登录用户信息时发现cookie没有带过去。查看请求发现登录请求的Set-Cookie响应头中的Path是/admin2。但是咱们请求的路径是/admin,cookie当然不会生效。 查阅文档发现,proxyTable支持onProxyRes回调函数来自定义响应,流程是通过替换后端服务器设置的cookie-path来进行处理,代码如下: proxyTable: { '/admin': { target: 'http://127.0.0.1:8080', changeOrigin: true, pathRewrite: { '^/admin': '/lesson/admin' }, onProxyRes: function (proxyRes, req, res) { const cookies = proxyRes.headers['set-cookie'] if (cookies) { const newCookies = cookies.map(cookie => { return cookie.replace(/Path=\/admin2/, 'Path=/') }) delete proxyRes.headers['set-cookie'] proxyRes.headers['set-cookie'] = newCookies } } },},重启webpack之后重新登录,发现cookie的路径已经被重写到/了。

July 10, 2019 · 1 min · jiezi

webpack初览webpack

webpack概念webpack 是一个打包工具。工作中很多时候因为时间关系,我们都有自己的任务,webpack配置的工作一般都是老大来解决。可是为了提高自己的竞争力,我觉得还是要抽时间来认真了解一下wepack。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。 配置webpack需要别人告诉它要怎么做,也就是配置。一般写在webpack.config.js中。配置项中最重要的有四大项: 入口输出loader插件入口[entry]入口是webpack读取文件的起点,他会进入入口然后根据依赖关系,找到用到的文件,处理打包。最终输出到bundles文件。 1.单个入口module.exports = { // 指定入口 entry: './path/to/my/entry/file.js'};module.exports = { // 指定入口 entry: { main: './path/to/my/entry/file.js' }};2.对象语法对象语法会比较繁琐。然而,这是应用程序中定义入口的最可扩展的方式。 const config = { entry: { app: './src/app.js', vendors: './src/vendors.js' }};出口[output]output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist。基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。 const path = require('path');module.exports = { entry: './path/to/my/entry/file.js', output: { // 输出路径 path: path.resolve(__dirname, 'dist'), // 输出文件名 filename: 'my-first-webpack.bundle.js' }};2. 多个入口起点假如入口配置了多个,出口要用占位符[name]来辨别输出的文件。 { entry: { app: './src/app.js', search: './src/search.js' }, output: { filename: '[name].js', path: __dirname + '/dist' }}// 写入到硬盘:./dist/app.js, ./dist/search.jsloaderwebpack 自身只理解 JavaScript,可是实际中我们会需要处理很多别的文件,如css,less,vue等等。这就是需要用loader。它是把这些文件转译成webpack能理解的文件。 ...

July 10, 2019 · 2 min · jiezi

webpack4详细教程从无到有搭建react脚手架四

相关链接 webpack4详细教程,从无到有搭建react脚手架(一)webpack4详细教程,从无到有搭建react脚手架(二)webpack4详细教程,从无到有搭建react脚手架(三)管理打包后目录结构打包结构如下 build/ js/ xxx.js css/ xxx.css images/ xxx.jpg index.html修改配置config/webpack.common.js function webpackCommonConfigCreator(options){ ... return { ... output: { - filename: "bundle.js", + filename: "js/bundle.js", path: path.resolve(__dirname, "../build"), }, module: { rules: [ ... { test: /\.(jpg|png|svg|gif)$/, use: [ { loader: 'url-loader', options: { limit: 10240, - name: '[hash].[ext]', + name: 'images/[hash].[ext]', } }, ] }, ] }, plugins: [ ... new ExtractTextPlugin({ - filename: "[name][hash].css" + filename: "css/[name][hash].css" }), ] } }通过相对output目录对资源命名前加上目录名 ...

July 9, 2019 · 2 min · jiezi

webpack4详细教程从无到有搭建react脚手架三

Css安装loaderyarn add style-loader css-loader -D配置config/webpack.common.js ... function webpackCommonConfigCreator(options){ ... return { ... module: { rules: [ ... + { + test: /\.css$/, + include: path.resolve(__dirname, '../src'), + use: ["style-loader", "css-loader"] + } ] }, ... } }创建src/app.css src/app.css .text{ font-size: 20px; color: brown; }src/App.js + import './app.css'; function App(){ return ( - <div> + <div className="text"> hello react </div> ) } ...yarn start, 效果: Scss安装loader yarn add sass-loader node-sass -D配置loaderconfig/webpack.common.js ... function webpackCommonConfigCreator(options){ ... return { ... module: { rules: [ ... { - test: /\.css/, + test: /\.(css|scss)$/, include: path.resolve(__dirname, '../src'), - use: ["style-loader", "css-loader"] + use: ["style-loader", "css-loader", "sass-loader"] } ] }, ... } }创建src/app.scss ...

July 9, 2019 · 3 min · jiezi

webpack4详细教程从无到有搭建react脚手架二

相关链接 webpack4详细教程,从无到有搭建react脚手架(一)配置插件 clean-webpack-plugin、 html-webpack-plugin, 这两个插件基本上是必配的了介绍clean-webpack-plugin - 每次打包时清理上次打包生成的目录 官网指南关于这个插件部分内容已经过时没有更新,按照官网配置会出错,所以参考github上这个插件文档来配置, 文档地址: https://github.com/johnagan/c... html-webpack-plugin - 生成打包文件中的 index.html安装yarn add clean-webpack-plugin html-webpack-plugin -D这两个插件在两种模式下都要用到,所以配置在common.jsconfig/webpack.common.js ... + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const { CleanWebpackPlugin } = require('clean-webpack-plugin'); function webpackCommonConfigCreator(options){ ... return { ... plugins: [ + new HtmlWebpackPlugin(), + new CleanWebpackPlugin({ + cleanOnceBeforeBuildPatterns: [path.resolve(process.cwd(), "build/"), path.resolve(process.cwd(), "dist/")] + }), ] } } ...更改开发代码,在页面上插入一个元素src/index.js var ele = document.createElement('div'); ele.innerHTML = "hello webpack"; document.body.appendChild(ele);效果yarn start, 效果: ...

July 9, 2019 · 2 min · jiezi

webpack4详细教程从无到有搭建react脚手架一

webpack 是一个现代 JavaScript 应用程序的静态模块打包器,前端模块化的基础。作为一个前端工程师(切图仔),非常有必要学习。 webpack官网的文档非常的棒,中文文档也非常给力,可以媲美vue的文档。建议先看概念篇章,再看指南,然后看API和配置总览。看完指南教程后,需要自主动手练习才能更加有影响,这里记录下我搭建react开发环境的过程 准备工作安装webpackyarn add webpack webpack-cli -D创建配置目录结构config webpack.common.js webpack.dev.js webpack.prod.jsscripts build.js // 构建模式脚本 start.js // 开发模式脚本src index.jspackage.json先尝试一个简单配置配置启动脚本命令package.json..."license": "MIT",+ "scripts": {+ "start": "node ./scripts/start.js",+ "build": "node ./scripts/build.js"+ },"devDependencies": { "webpack": "^4.35.2", "webpack-cli": "^3.3.5"}...编写webpack配置, 以 src/index.js 作为主入口,以 build为打包后的目录config/webpack.common.jsoutput path字段这里配置的绝对路径 const path = require('path'); module.exports = { entry: "./src/index.js", output: { path: path.resolve(__dirname, "../build"), filename: "bundle.js" } }编写开发模式运行脚本scripts/build.js const webpack = require('webpack'); const webpackConfig = require('../config/webpack.common.js'); webpack(webpackConfig, (err, stats) => { if(err || stats.hasErrors()){ console.log("编译失败"); } });webpack node接口文档: https://www.webpackjs.com/api... ...

July 9, 2019 · 2 min · jiezi

canvaswebpack构建flappybird小游戏

效果链接 github地址

July 9, 2019 · 1 min · jiezi

vuecli脚手架工具搭建vuewebpack项目

vue-cli构建工具大大降低webpack的使用难度,支持热更新,有webpack-dev-server的支持,相当于启动了一个请求服务器,给你搭建了一个测试环境,只关注开发。 1.使用vue-cli之前,需要安装node环境,详细教材参考https://www.cnblogs.com/xinai... 2.使用npm全局安装webpack打开命令行工具输入:npm install webpack -g或者(npm install -g webpack),安装完成之后输入 webpack -v,如下图,如果出现相应的版本号,则说明安装成功。 3.全局安装vue-cli在cmd中输入命令:npm install --global vue-cli,安装完成之后输入 vue -V(注意这里是大写的“V”),如下图,如果出现相应的版本号,则说明安装成功。 4.vue-cli来构建项目在D盘新建一个文件夹(vue_project)作为项目存放地,然后使用命令行cd进入到项目目录输入:vue init webpack vue-test 输入命令后,会跳出几个选项让你回答:Project name (vue-test):项目名称,直接回车,按照括号中默认名字(注意这里的名字不能有大写字母,如果有会报错Sorry, name can no longer contain capital letters)Project description (A Vue.js project):项目描述,也可直接点击回车,使用默认名字Author ():作者Runtime + Compiler: recommended for most users 运行加编译,既然已经说了推荐,就选它了Runtime-only: about 6KB lighter min+gzip, but templates (or any Vue-specificHTML) are ONLY allowed in .vue files - render functions are required elsewhere 仅运行时,已经有推荐了就选择第一个了Install vue-router? (Y/n) 是否安装vue-router,这是官方的路由,大多数情况下都使用,这里就输入“y”后回车即可。Use ESLint to lint your code? (Y/n) 是否使用ESLint管理代码,ESLint是个代码风格管理工具,是用来统一代码风格的,一般项目中都会使用。接下来也是选择题Pick an ESLint preset (Use arrow keys) 选择一个ESLint预设,编写vue项目时的代码风格,直接y回车Setup unit tests with Karma + Mocha? (Y/n) 是否安装单元测试,我选择安装y回车Setup e2e tests with Nightwatch(Y/n)? 是否安装e2e测试 ,我选择安装y回车回答完毕后就开始构建项目 ...

July 8, 2019 · 1 min · jiezi

报错webpack不是内部或不可执行命令

【01】报错:webpack不是内部或不可执行命令。 一般来安装完之后是可以直接执行的你可以执行 webpack -v 或者是 webpack --help 这样的就是正确的,我的问题的解决办法是 将你的webpack.cmd的可执行文件的手动配置到环境变量里 我的webpack.cmd的目录在 C:ProgramFiles/nodejs/node_global 最后成功就成功了

July 8, 2019 · 1 min · jiezi

Webpack-技巧-联合-alias-和-mainFields-提高多库联调效率

1、多库联调场景目前在开发一个工程项目,考虑到可扩展性和功能解耦,将每个功能模块都单独拆分出来。在正式使用、单独维护某个功能包的时候没什么问题,最为头疼的是联调两个功能模块的时候,就比较掣肘了。 我们举下面的场景为例来说明: 工程项目中有 A、B、C 这 3 个功能模块,每个功能模块都是单独的一个 npm 包;其中 A 是基础工具包,B、C 是业务功能模块;C 包依赖 A 包的功能工程目录及引用关系如下图所示: 1.1、联调的难题当我们开发 C 模块的时候,需要 同时联调 A 模块的功能,而由于 A 模块是以 npm 包放在在 node_modules 中,所以我们直接修改 A 模块并没有什么用,修改的效果并不会出现的 C 模块的调试内容中。 1.2、通常的解决方案通常我们的解决方法是采用 npm link 方式解决:先在 A 模块下执行 npm link;然后去 C 模块中执行 npm link A,这样我们就能方便联调这两个模块。 然而这种 npm link 的方式在某些场景还是有限制: 如果你使用 Typescript 开发,npm link 后有可能会报错找不到 A 模块中的 xx 类型定义;这个目前我也没有找到好的解决方案。。。如果 A 包只以压缩版本发行(即 dist 目录只存 index.min.js 文件),那么你每次修改 A 文件后必须手动打包一次,那么 C 模块才会感知文件的变化触发 hot reload如果没有上述这两个问题,我以往我都直接使用 npm link 的方式联合开发,联调地也是蛮开心的。 ...

July 7, 2019 · 1 min · jiezi

一次项目中的验签加密的一些坑主要是数据格式问题

最近接手了一个项目是一个比较完整的项目了 我需要进行改造 是基于vuecli3.0+webpack开发的u其中有一个功能就是我们每个请求都要进行一次验签 就是取一些字符串进行加密 并将验签加入请求头中 后台也用相同的算法进行加密 然后比对这个功能本身是写好的 但是有些问题我们其中的加密字段是穿的参数按照字母排序 然后取第一个参数的前三位和最后一个参数的后三位这都很简单用sort()方法排序一下就行第一个问题就是axios直接传值的话服务端会认为是字符串所以截取的时候会将符号也截取一般就成了{"+排序第一的参数的第一个字母和排序最后一个参数的最后一个字母 + "} 这样明显是有问题的 不过这个解决也简单 直接用qs这个插件处理一下就ok 这里我做了一个处理 如果requestData是类型是字符串 用 requestData.split('&').sort().join('').replace(/([^=><])=([^=><])/g,'$1$2');进行排序如果是对象 用 for (var i in requestData) { dataString += `${i}${requestData[i]}&` } dataString = dataString.split('&').sort().join('')进行排序这样就解决了大部分的问题 但是昨天突然有一个模块说验签又不过了 我就很奇怪 就让后端小哥把没加密的串返回给我对比了一下首先还是我上面说的截取到了符号 这个简单 qs处理一下然后这里的问题是用qs处理过后 参数中如果带有中文 后端接收到的其实是中文 但是qs自己会对中文进行encodeURIComponent转码 这个处理也很简单 使用decodeURIComponent() 函数进行解码就可以

July 6, 2019 · 1 min · jiezi

CodeSandbox-浏览器端的webpack是如何工作的-上篇

这期来关注一下CodeSandbox, 这是一个浏览器端的沙盒运行环境,支持多种流行的构建模板,例如 create-react-app、 vue-cli、parcel等等。 可以用于快速原型开发、DEMO 展示、Bug 还原等等. 相似的产品有很多,例如codepen、JSFiddle、WebpackBin(已废弃). CodeSandbox 则更加强大,可以视作是浏览器端的 Webpack 运行环境, 甚至在 V3 版本已经支持 VsCode 模式,支持 Vscode 的插件和 Vim 模式、还有主题. 另外 CodeSandbox 支持离线运行(PWA)。基本上可以接近本地 VSCode 的编程体验. 有 iPad 的同学,也可以尝试基于它来进行开发。所以快速的原型开发我一般会直接使用 CodeSandbox 目录 引基本目录结构项目构建过程 Packager WebpackDllPlugin在线打包服务回退方案Transpilation 基本对象ManagerTranspiledModuleTranspilerBabelTranspilerEvaluation技术地图扩展引 笔者对 CodeSandbox 的第一印象是这玩意是运行在服务器的吧? 比如 create-react-app 要运行起来需要 node 环境,需要通过 npm 安装一大堆依赖,然后通过 Webpack 进行打包,最后运行一个开发服务器才能在浏览器跑起来. 实际上 CodeSandbox 打包和运行并不依赖于服务器, 它是完全在浏览器进行的. 大概的结构如下: Editor: 编辑器。主要用于修改文件,CodeSandbox这里集成了 VsCode, 文件变动后会通知 Sandbox 进行转译. 计划会有文章专门介绍CodeSandbox的编辑器实现Sandbox: 代码运行器。Sandbox 在一个单独的 iframe 中运行, 负责代码的转译(Transpiler)和运行(Evalation). 如最上面的图,左边是Editor,右边是SandboxPackager 包管理器。类似于yarn和npm,负责拉取和缓存 npm 依赖CodeSandbox 的作者 Ives van Hoorne 也尝试过将 Webpack 移植到浏览器上运行,因为现在几乎所有的 CLI 都是使用 Webpack 进行构建的,如果能将 Webpack 移植到浏览器上, 可以利用 Webpack 强大的生态系统和转译机制(loader/plugin),低成本兼容各种 CLI. ...

July 5, 2019 · 6 min · jiezi

Webpack重要知识点

最近在系统整理知识点,现将Webpack的一些重要知识点罗列出来,方便快速查阅。Tree Shaking为了使用tree shaking,需要满足以下条件: 使用ES2015语法(即import和export)在项目package.json文件中,添加sideEffects入口引入一个能够删除未引用代码(dead code)的压缩工具(minifier)(例如:UglifyJSPlugin)将文件标记为无副作用(side-effect-free)这种方式是通过package.json的sideEffects属性来实现的。 { "sodeEffects": false}「副作用」的定义是,在导入时会执行特殊行为的代码,而不是仅仅暴露一个export或多个export。举例说明,例如polyfill,它影响全局作用域,并且通常不提供export。注意,任何导入的文件都会受到tree shaking的影响。这意味着,如果在项目中使用类似css-loader并导入CSS文件,则需要将其添加到 side effect 列表中,以免在生产模式中无意中将它删除: { "sideEffects": ['*.css']}压缩输出从 webpack 4 开始,也可以通过 "mode" 配置选项轻松切换到压缩输出,只需设置为 "production"。也可以在命令行接口中使用--optimize-minimize标记,来使用UglifyJSPlugin。 Code Splittingcode splitting的必要性 不进行code splitting,打包后单文件提交较大,加载时长较长,影响用户体验不进行code splitting,经常修改业务代码,重新打包后,浏览器不能进行缓存,导致性能较差,影响用户体验code splitting的配置同步代码方式import _ from 'lodash';webpack.common.js配置如下: ....optimization: { splitChunks: { chunks: 'all' }}....配置后,会将公用类库进行打包,生成一个vendors~main.js文件。 异步代码方式function getComponent() { return import('lodash').then(({ default: _ }) => { var element = document.createElement('div'); element.innerHTML = _.join(['Clear', 'love'], ''); return element; })}getComponent().then(element => { document.body.appendChild(element);})SplitChunksPlugin 配置参数详解魔法注释(magic comment)修改打包动态组件名称1. 使用@babel/plugin-syntax-dynamic-import支持动态引入插件在.babelrc中引用该插件 ...

July 5, 2019 · 2 min · jiezi

vuecli3-取消eslint-校验代码

vue create hello-world创建项目的时候选择了Linter / Formatter,所以写代码的时候会有代码规范检查,怎么才能关闭这个校验呢 1.项目创建好后会生成 .eslintrc.js文件 module.exports = { root: true, env: { node: true }, 'extends': [ 'plugin:vue/essential', // '@vue/standard',//这行注释就可以 '@vue/typescript' ], rules: { 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' }, parserOptions: { parser: '@typescript-eslint/parser' }}@vue/standard 这个注释掉就可以了

July 5, 2019 · 1 min · jiezi

为什么选择Webpack

社区活跃生态丰富 官方迭代速度快维护好6月10-6月17 一周的活跃情况 配置灵活和插件化扩展配置很灵活对于不满足一些开发需要的,也是可以通过webpack插件机制进行扩展。定义自己的loader和plugin去满足自己团队个性化的需求。官方维护的loader和plugins很多 参考:官方维护的loader官方维护的pluginswebpack活跃度参考

July 5, 2019 · 1 min · jiezi

Webpack与GruntGulp的区别

随着前端发展如日冲天,前端项目也越来越复杂,得益于Nodejs的发展,前端模块化、组件化、工程化也大势所趋。这些年Grunt、Gulp到Webpack随着工程化的发展都大行其道。 前端工程化的早期,主要是解决重复任务的问题。Grunt、Gulp就是其中代表。比如: 压缩、编译less、sass、地址添加hash、替换等。 Grunt官网中就说: 对于需要反复重复的任务,例如压缩(minification)、编译、单元测试、linting等,完成大部分无聊的工作。而如今的Webpack更像一套前端工程化解决方案。利用强大插件机制,解决前端静态资源依赖管理的问题。 Webpack作者Tobias回复与 Grunt Gulp NPM脚本的比较Tobias: NPM脚本对我而言足矣。实际上,说webpack是Grunt/Gulp的替代器并不完全准确。Grunt和Gulp以及NPM脚本都是任务执行程序。Webpack是_模块打包程序_。这两类程序的目标不一样。但webpack简化了必须“过度使用”Grunt和Gulp和NPM脚本才能实现的Web开发任务也是事实。NPM脚本才是Grunt和Gulp的替代品。不过,除了纯粹的构建之外,任务运行程序也有存在的理由,比如部署、代码检查、版本管理,等等。 Webpack与Grunt、Gulp运行机制# grunt gulp 思路【遍历源文件】->【匹配规则】->【打包】做不到按需加载,对打包的资源,是否用到,打包过程不关心。# webpack【入口】->【模块依赖加载】->【依赖分析】->【打包】在加载、分析、打包的过程中,可以针对性的做一些解决方案。比如:code split(拆分公共代码) Grunt与Gulp性能比较Grunt: 每个任务处理完成后存放在本地磁盘.tmp目录中,有本地磁盘的I/O操作,会导致打包速度比较慢。Gulp: gulp与grunt都是按任务执行,gulp有一个文件流的概念。每一步构建的结果并不会存在本地磁盘,而是保存在内存中,下一个步骤是可以使用上一个步骤的内存,大大增加了打包的速度。 参考:grunt官网webpack作者接受参访文章

July 3, 2019 · 1 min · jiezi

Webpack是什么

背景webpack的作者是德国纽伦堡Tobias Koppers,   webpack的诞生之初主要是想解决代码的拆分问题。这也是webpack这么受欢迎的原因所在。同时也离不开500多位开源贡献者。 解释webpack 是一个现代 JavaScript 应用程序的静态模块打包工具。当 webpack 处理应用程序时,它会在内部构建一个 依赖图(dependency graph),此依赖图会映射项目所需的每个模块,并生成一个或多个 _bundle_。 这是官方文档给出的webpack的解释,这里我提取几个关键词理解。 理解模块模块,又称构件,是能够单独命名并独立地完成一定功能的程序语句的集合(即程序代码和数据结构的集合体)。它具有两个基本的特征:外部特征和内部特征。外部特征是指模块跟外部环境联系的接口(即其他模块或程序调用该模块的方式,包括有输入输出参数、引用的全局变量)和模块的功能;内部特征是指模块的内部环境具有的特点(即该模块的局部数据和程序代码)。 以上是百度百科给模块的定义,前端模块化一般指javascript的模块,最常见的模块就是npm包。每一个模块可能是最小甚至是最优的代码组合。 静态模块打包工具将javascript代码、与其他静态文件组成的不同模块,进行分析、解析压缩打包成浏览器可识别的代码的过程。 依赖图(dependency graph)任何时候,一个文件依赖于另一个文件,webpack 就把此视为文件之间有_ 依赖关系_。webpack从命令行或配置文件定义的一个模块列表开始,处理你的应用程序;从入口开始webpack递归的构建一个依赖图,这个依赖图包含着应用程序中所需的每个模块,然后将这些模块打包成少量的bubdle,使浏览器可以执行。 通过上图能够简单理解,webpack就像一个黑盒子,通过这个黑盒子的模块(js、ts、png、sass等),将最终转化成浏览器可识别的文件。 Webpack能做什么?代码转换、文件优化、代码分割、模块合并、自动刷新、代码校验、自动发布 参考:百度百科模块定义官网给出的模块解释官网依赖图解释

July 3, 2019 · 1 min · jiezi

前端历史演变

在选择学习Webpack之前,我们先了解一下前端整个发展历程。 2014年初,我加入互联网开发行业,随没经历前端刀工火种的时态,5年的时间,前端技术的百家齐放很是眼花缭乱。我也从套页面后端工程师、jquery写效果到现在的小程序、node、vue转变成一个纯前端。现在回顾一下前端到底发生了哪些历史变化。 静态页面 1990~2005互联网发展早期,前端只负责写静态页面,纯粹的展示功能,JavaScript的作用也只是增加一些特殊效果。这种静态页面不能读取数据库,为了使Web更加充满活力,以PHP、JSP、ASP.NET为主的动态语言相继诞生。这使页面能够获取数据并不断更新,是前后端混合开发模式开端,所有的前端代码和前端数据都是后端生成的,随着后端代码的庞大和逻辑越来越复杂,相继的MVC发展起来。这时后端大多采用MVC模式开发,前端只是后端MVC中的V(视图);从web的诞生到2005,一直处在_后端重前端轻_的状态。 AJAX阶段 20052004年AJAX技术的诞生改变了前端的发展历史。以Gmail和Google地图这样革命性的产品出现,使得开发者发现,前端的作用不仅仅是展示页面,可以管理数据和用户互动。解决一些糟糕的用户体验,前端页面要想获取后台数据需要刷新整个页面。依稀记得前几年,依托强大的Jquery,一页面的javascript代码使用ajax发送请求渲染DOM的情景。前端开始慢慢向后端靠拢。 NODEJS 的爆发 20092009年Ryan Dahl利用Chrome的V8引擎打造了基于事件循环的异步I/O框架。NODE的诞生,使javascript在服务端的无限可能,更重要的是它构建了一个庞大的生态系统。 2010年1月,NPM作为node的包管理系统首次发布。开发人员可以依照规范编写nodejs模块,发布到npm上,供其他开发人员下载使用。截止目前2019年6月8日,NPM包数量有1,003,262,是世界上最大的包模块管理系统。 Node.js 给开发人员带来了无穷的想象,JavaScript 大有一统天下的趋势。 前端MV**架构阶段 2010随着 HTML5 小程序 的流行,前端再也不是人们眼中的小玩意了,应用功能开发逐步迁移到了前端,前端的代码逻辑逐渐变得复杂起来。2010年10月Backbone MVP架构发布。2010年10月Angular MVC->MVVM2013年05月React开源 MVVM2014年07月Vue MVVM 随着这些 MV* 框架的出现,网页逐渐由 Web Site 演变成了 Web App,最终导致了复杂的单页应用( Single Page Application)的出现。随着 SPA 的兴起,2010年后,前端工程师从开发页面(切模板),逐渐变成了开发“前端应用”(跑在浏览器里面的应用程序)。 javascript 开发App随着 iOS 和 Android 等智能手机的广泛使用,移动浏览器也逐步加强了对 HTML5 特性的支持力度。 Web APP,即移动端的网站。一般泛指 SPA(Single Page Application)模式开发出的网站。将页面部署在服务器上,然后用户使用各大浏览器访问,不是独立APP,无法安装和发布。 Hybrid App,即混合开发,也就是半原生半Web的开发模式,有跨平台效果,实质最终发布的仍然是独立的原生APP。 React Native App,Facebook发起的开源的一套新的APP开发方案,使用JS+部分原生语法来实现功能。 May 7, 2019谷歌发布 Flutter for web,正式宣布 Flutter 成为全平台框架,支持手机、Web、桌面电脑和嵌入式设备。现在学跨平台应用开发,第一个要看的可能不是 React Native,而是 Flutter。 ...

July 3, 2019 · 1 min · jiezi

基于WebpackTypeScriptKoa的环境配置

TypeScript是一种开源编程语言,在软件开发社区中越来越受欢迎。TypeScript带来了可选的静态类型检查以及最新的ECMAScript特性。作为Javascript的超集,它的类型系统通过在键入时报告错误来加速和保障我们的开发,同时越来越多对的库或框架提供的types文件能够让这些库/框架的API一目了然。我对这门语言垂涎已久,但是迟迟无法找到练手的地方。很显然的,个人博客又一次的成了我的学习试验田????。我放弃了上一版Vue单页面的框架,改为基于TypeScript/Koa的多页面应用。在改造的过程中,我试着将服务端(Koa)代码以及前端代码都使用TypeScript来开发,中间使用了webpack作为开发时前后端的桥梁。 目录结构.├── .babelrc├── bin│ ├── dev.server.ts│ ├── pm2.json│ └── app.ts├── config # 配置目录│ ├── dev.ts│ └── prod.ts├── nodemon.json├── package.json├── postcss.config.js├── scripts│ └── webpack.config.js├── src # 源码│ ├── assets # 静态资源│ │ ├── imgs│ │ ├── scss│ │ └── ts│ ├── entries # webpack入口│ │ ├── blog.ts│ │ └── index.ts│ └── views # 模板(文件名与入口一一对应)│ ├── blog.html│ ├── index.html│ └── layout # 模板布局│ ├── footer.html│ └── header.html├── server # 服务端│ ├── app.ts│ └── middleware│ └── webpack-dev-middleware.ts├── test # 单元测试│ └── .gitkeep ├── tsconfig.front.json└── tsconfig.json安装项目依赖npm i --save koa koa-{router,bodyparser,static,ejs}npm i -D typescript ts-node nodemon @types/{node,koa,koa-router,koa-bodyparser}开发环境(development)流程 ...

July 2, 2019 · 3 min · jiezi

Vuejs-SSR-内容总结

本文只是对Vue.js官方SSR文档和对官方hackernews demo的个人学习总结,说得不够完整的请见谅本文主要对以下几方面内容对Vue.js SSR的内容进行分析总结 SSR出现的原因Vue.js SSR的总体原理SSR当中的数据预取SSR在编写代码时候的限制SSR的webpack构建原理SSR出现的原因单页应用有一个很大的缺点就是SEO问题,搜索引擎目前只能对同步的javascript进行索引,但对于需要异步获取数据的单页应用来说,搜索引擎并不会抓取到它们的内容更快的首屏内容展示速度,单页应用需要等待JS文件加载完成,然后再进行页面渲染,而SSR是将渲染完毕的html传输给客户端Vue.js SSR的总体原理如果用一句话概括Vue.js SSR的运作过程,那就是在服务端将Vue.js实例转换成html字符串传输到客户端,然后进行客户端激活,使网页内容能在Vue实例的控制之下 这一句话包含两步内容 Vue.js实例转换成html字符串客户端激活先来看第一步 Vue.js应用转换成html字符串一个最简单的Vue.js单页应用是这样的: new Vue({ render: h => h('div', '123')}).$mount('#app')这里也包含两步 新建Vue实例挂在到DOM上面在服务端当中我们不进行上面第二步操作,取而代之的是将这个实例直接渲染成字符串,做这个工作的就是我们的vue-server-renderer const renderer = require('vue-server-renderer').createRenderer()const Vue = require('vue')renderer.renderToString(new Vue({ render: h => h('div', 123)})).then(html => { console.log(html)}).catch(err => { console.error(err)})// 输出<div data-server-rendered="true">123</div>到现在一个最简单的vue ssr应用在服务端的工作已经完成了,下面我们转向下一步客户端激活 客户端激活客户端激活跟我们单页应用所做的工作相比,最大的不同点就是它并不会构建DOM元素,只会对现有的DOM元素进行激活,使它们能被Vue实例进行控制,而判断激活的关键就是上面的data-server-rendered属性 至此,最简单的一个SSR应用已经构建完成了,下面是对这个应用的功能进行进一步的补充 SSR当中的数据预取数据预取包含着两个方面,客户端的数据预取和服务端的数据预取 服务端的数据预取我们渲染一个内容完整页面的时候往往需要向服务器请求数据,所以现在服务端的逻辑变成等待数据获取完毕,然后将页面转换成html字符串 其中数据获取有以下几个问题: 获取哪些数据?如何得到获取数据的方法?应在何时预取数据?预取的数据应保存在哪里?预取的数据应该怎么样跟客户端进行同步?问题1:我们的数据用来渲染页面,那么我们就需要组成当前页面的所有组件各自所需要的数据 问题2:每个需要进行服务端数据预取的组件定义一个asyncData方法,此方法用于数据预取 问题3:我们需要先得到当前页面所有需要渲染的组件,然后再进行数据预取 问题4:由于还需要进行数据同步,所以很难将数据保存在组件的私有data上面,放在vuex上面是个普遍的选择 问题5:服务端在返回html字符串的时候,store数据将被序列化以后以window.__INITIAL_STATE__=/* store state */的形式插入到脚本当中被客户端获取,客户端的store使用store.replaceState方法同步state 简单复述一下上面的流程就是:在渲染当前页面的所有组件加载完毕以后,执行这些组件的asyncData方法,这些方法将获取到的数据将由vuex托管,获取数据完毕以后即可将应用渲染成html字符串,vuex store的state将会被序列化以后一并传输到客户端,被客户端进行同步 下面是实现的一些细节: 判断组件加载完毕的方法是vue-router的onReady方法获取当前页面的所有组件为vue-router的getMatchedComponents方法由于源码太长所以没贴出来,具体可以到官网浏览 服务端数据预取的关键点算是总结的差不多了,下面简单说一下客户端的数据预取 客户端数据预取客户端的数据预取方法可分为两种: 等待数据获取完毕后再进行视图切换先进行视图切换然后在进行数据获取两种方法区别在于让用户在什么时候产生等待的感觉,第一种是在页面切换时,而第二种是在页面切换完毕等待内容的出现时 第一种方法的实现使用了vue-router实例的beforeResolve方法,这个方法执行在异步组件加载完毕后,导航被确认之前,当完成数据预取以后router才会进行DOM更新等步骤 第二种方法的实现跟我们一般进行数据获取一致,在beforeMount钩子当中执行 SSR在编写代码时候的限制由于浏览器特定的API将会在服务端报错,如'document'、'window'等,尽量避免使用此类API或者在非服务端运行的声明周期函数中调用如'mounted'等等指令由于能直接操作DOM会受到很大的限制SSR的webpack构建原理以官方的hackernews demo为例,webpack有两个入口entry-client和entry-server分别负责构建客户端和服务端的文件 服务端方面webpack会输出一个名叫vue-ssr-server-bundle的json文件,此文件由官方提供的VueSSRServerPlugin插件所构建而成,是服务端的构建清单,传入createBundleRenderer生成服务端渲染所需要的renderer 客户端方面webpack输出的是由代码分割而成的chunk和公用bundle,与一般单页应用的构建相似,不同的是会生成一个vue-ssr-client-manifest,此文件是客户端方面的构建清单,包含所有chunk的信息,将其传入上面的renderer当中能自动将chunk嵌入到html当中,当然用户也能够取消,自行选择手动嵌入的内容 ...

July 1, 2019 · 1 min · jiezi

webpack

webpack时间note - 11.15webpack.config.js - 32.28 33.00package.json - 其余更改配置文件名 - npx webpack -- config webpack.config.my.js本地服务 - yarn add webpack-dev-server -D 27.46生成模版 - yarn add html-webpack-plugin -D 32.05 dev - 写到内存中·静态服务 csscss 模块引入css-loader - 43.30 - @importyarn add css-loader style-loader -D style-loader - 放在style标签中 less - 49.10 yarn add sassstylus 49.40 min-css-extract-pulgin - 51.52 抽离样式 需要自己压缩文件-增加浏览器前缀 - postcss-loader - 56.25 58.59 npm install --save-dev postcss-loader autoprefixnpm install --save-dev terser-webpack-pluginnpm install --save-dev optimize-css-assets-webpack-pluginnpm install --save-dev mini-css-extract-plugin ...

July 1, 2019 · 1 min · jiezi

crossenv使用以及根据环境打包

关于之前的项目打包都是靠手动去改环境变量(纯属沙雕行为),随着项目越来越多,每一个项目打包都要去改这个变量的话真的是太蛋疼了,所以研究了一下webpack打包以及node env主要这样做有什么好处? publicPath: process.env.APP_ENV === 'production' ? 'https://cdn.xxxx.com/brand-mall-chengdong/' : '/', outputPath: './brand-mall-chengdong',之前都是每次打包手动修改这个静态资源的地址,修改之后根据环境变量自动区分 第一步,安装cross-envyarn add cross-env@5.1.1 cross-port-killer@1.0.1 什么是cross-env?解:当您使用NODE_ENV=production类似设置环境变量时,大多数Windows命令提示将会阻塞 。(例外是Windows上的Bash,它使用本机Bash。)同样,Windows和POSIX命令如何利用环境变量也有所不同。使用POSIX,您可以使用:$ENV_VAR 和您使用的Windows %ENV_VAR%。第二步,修改package.json文件 "build": "cross-env APP_ENV=production umi build", "build:test": "cross-env APP_ENV=test umi build",新增一条如上命令,当执行npm run build时,设置proess.env.APP_ENV为production ,同理设置为test.然后在config.js文件中即可根据这个变量设置相应的路径。 关于文章首发于cross-env使用以及根据环境打包

June 30, 2019 · 1 min · jiezi

WebAssembly应用到前端工程下-webpack和webassembly

在上一篇文章WebAssembly应用到前端工程(上)—— webassembly模块的编写中,完成了@ne_fe/gis模块的编写与发布。然而webassembly在当前以webpack4为主要编译工具的实际工程应用中依然存在问题。尽管webpack4新增了对wasm文件的编译支持,在wasm模块编写完成之后将其与webpack结合的过程中发现,wasm模块无法被正确加载。在对@ne_fe/gis编译输出文件的检查之后,有了新的解决方案 wasm-module-webpack-plugin。 出现的问题直接在前端工程中引入@ne_fe/gis并使用的话,控制台会输出错误信息 index.js?558c:1 GET http://localhost:8080/gps.wasm 404 (Not Found)Uncaught (in promise) TypeError: Incorrect response MIME type. Expected 'application/wasm'.查看所引用的@ne_fe/gis/dist/index.js后发现这样一句话 var Pn="undefined"!=typeof location?location.pathname.split("/"):[];Pn.pop(),(Cn?WebAssembly.instantiateStreaming(fetch(Pn.join("/")+"/gps.wasm"),o):fetch(Pn.join("/")+"/gps.wasm").then(e=>e.arrayBuffer()).then(e=>WebAssembly.instantiate(e,o)))出错原因时由于fetch直接从根路径下直接获取wasm文件,但文件并没有生成或移动,webpack并不能处理fetch所加载的文件,最终导致wasm加载失败。 babelwebpack不能处理js的fetch语句,导致了上面问题的出现,那么只有一种方法能够处理fetch语句,那就是babel。下面来编写一个babel插件处理fetch加载wasm的情况 // babel-plugin.jsmodule.exports = function() { return { visitor: { CallExpression(path, state) { if(path.node.callee.name === 'fetch'){ const argument = JSON.parse(JSON.stringify(path.node.arguments[0])); for (const i in argument.right) { if (i === 'value' && argument.right[i].endsWith('.wasm')) { console.log('argument.right[ i ]', argument.right[ i ], 'state.file.opts.filename', state.file.opts.filename); } } } }, } }};在webpack中使用 ...

June 28, 2019 · 2 min · jiezi

angularjs在webpack下使用require引用户html文件时出现-moduleexports-n

原因猜想:使用html-loader加载了两次html 比如,错误示例: module: { rules: [ // all files with a '.ts' or '.tsx' extension will be handled by 'ts-loader' {test: /\.ts$/, loader: "ts-loader"}, {test: /\.(html)$/, loader: "html-loader"}, {test: /\.html/, loader: "html-loader"} ] },则在代码中看到require('./yunzhi.html')时。首先,由于符合第一条 {test: /\.(html)$/, loader: "html-loader"},则将html编译为变量A -> (module.exports);然后,由于再次符合第二条规则{test: /\.html/, loader: "html-loader"},又重新将A进行了二次编译,然后就出现了我们不想看到的。 例子a.html <yunzhi></yunzhi>yunzhi组件 app.component('yunzhi', { template: require('./yunzhi.html') ...});yunzhi.html <h1>hello</h1><h2>hello</h2>则发生如下错误: 解决方案删除冗余的loader删除前: module: { rules: [ // all files with a '.ts' or '.tsx' extension will be handled by 'ts-loader' {test: /\.ts$/, loader: "ts-loader"}, {test: /\.(html)$/, loader: "html-loader"}, {test: /\.html/, loader: "html-loader"} ] },删除后: ...

June 28, 2019 · 1 min · jiezi

webpack进阶

基于 webpack 提供的接口,社区可以贡献各种 loader 和 plugin,组合使用可以使得 webpack 的功能很丰富强大。常用 loadersass-loader,css-loader,style-loader => 加载样式url-loader => 加载文件,如字体文件和图片文件html-loader => 加载模板文件babel-loader => 加载 js 和 jsx 文件awesome-typescript-loader => 加载 ts 文件常用 Pluginhtml-webpack-plugin安装依赖npm install html-webpack-plugin --save-dev配置 modules// webpack.config.jsconst HtmlWebpackPlugin = require('html-webpack-plugin')module.exports = { // ... modules:[ new HtmlWebpackPlugin({ template:'./index.html', // 引用的模板 filename:'index.html', // 打包后的命名 inject:true, // 是否自动引入打包的js文件 }) ]}引用中的模板(index.html)可以使用一些变量及简单的分支// index.html<% if(process.env.NODE_ENV==='development'){ %> 1313<% } %><script> console.log(<%= JSON.stringify(process) %>); console.log(<%= JSON.stringify(process.env) %>);</script>其中 JSON.stringify(process),解析为一个对象 ,JSON.stringify(process.env) 为空对象 ...

June 26, 2019 · 1 min · jiezi

一个快速开发响应式网站的有趣的偏视觉交互的前端开发工具箱-套件-Uix-Kit

这个产品维护已经有一年了(由于业务需求不同,产品本身是针对国外网站和WordPress的需求搭配),自己本身是做UI出生,开发只是业余爱好,仅仅作为平时工作的需要。杂七杂八会一些前后端开发。并非职业码农! 我是一个BBoy,也是一个爱到处旅行拍极限视频的冒险家!喜欢大自然,不喜欢繁华都市。 好啦,自我介绍简单就好!:) Uix Kit —— 它是一个偏视觉交互的工具集合,它基于常用的脚本库,帮助开发者快速完成一套完整的交互型网站。 项目地址: https://github.com/xizon/uix-kit 它不是一个框架,不是一个脚本库,它是一个兼容Bootstrap的快速建站HTML5套件,遵循W3C标准,包括手风琴、Tab切换、大型导航、单页、视差、分页、项目符号列表、文章列表、网格系统、AJAX交互、常用的多风格轮播、视频、计数器、作品画廊展示、模态弹窗、简易灯箱、无限滚动加载、鼠标交互、滚动侦听动画、时间轴、按钮、多风格Footer、文字效果、徽章、表单等等常用的网站模块,并支持官方无限更新和扩展、优化,满足各类常用的、交互和动效级的Web前端开发需求。支持Gulp和Webpack开发模式。套件提供了规范的HTML结构和模块化的HTML,CSS,JS代码(默认),能够让开发者快速进入开发模式,自定义、修改或删除任意模块。 设计初衷:现在很多普通网站,已经可以通过在线的拖拽建站工具,智能建站系统快速完成,因此普通网站已经无需专门花很多金钱和时间去找一个开发者完成。Uix Kit工具箱是针对一些特殊效果的交互的网站,也可以用于比较个性化的定制网站的开发设计。 套件结构:uix-kit/├── README.md├── CHANGELOG.md├── CONTRIBUTING.md├── LICENSE├── webpack.config.js├── package-lock.json├── package.json├── dist/│ ├── css/│ │ ├── uix-kit.css│ │ ├── uix-kit.css.map│ │ ├── uix-kit.min.css│ │ ├── uix-kit.min.css.map│ │ ├── uix-kit-rtl.css│ │ ├── uix-kit-rtl.css.map│ │ ├── uix-kit-rtl.min.css│ │ └── uix-kit-rtl.min.css.map│ └── js/│ │ ├── uix-kit.js│ │ ├── uix-kit.js.map│ │ ├── uix-kit.min.js│ │ ├── uix-kit.min.js.map│ │ ├── uix-kit-rtl.js│ │ ├── uix-kit-rtl.js.map│ │ ├── uix-kit-rtl.min.js│ │ └── uix-kit-rtl.min.js.map├── misc/│ ├── screenshots/│ └── grid/├── src/│ ├── index.js│ ├── index-rtl.js│ ├── components/│ │ ├── ES5/ => Third-party plugins adopt pure file merger and do not import and export│ │ └── ES6/ => Core modules├── examples/│ ├── *.html│ ├── assets/│ │ ├── css/│ │ ├── fonts/│ │ ├── images/│ │ ├── videos/│ │ ├── models/│ │ ├── json/│ │ └── js/└──演示https://xizon.github.io/uix-kit/examples/ ...

June 24, 2019 · 1 min · jiezi

Vue组件库开发总结

Vue组件库开发总结由于工作需要,最近在学习怎么开发一个Vue组件库。主要需要实现以下点:1.组件使用npm包引入2.实现按需引入及按需打包项目中许多实现是参考的element-ui,特别是webpack打包部分 组织项目项目生成项目生成是直接用的vue-cli,在根目录下增加了一个index.js,用于组件打包的入口文件,两个webpack打包文件,以及一个组件的json文件,用于之后的按需引入的打包。组件放置在src/cmps中,目录结构如下图: 组件结构由于我的组件把样式都写在了vue里面,所以没有单独的样式文件,就是一个Vue文件和一个js入口文件 组件编写单个组件编写vue组件的编写需要按照官方的vue插件开发规范来。为了实现后续的按需打包,在每一组件的入口文件中,都需要定义install方法,并随组件一同暴露出来 import Button from './index.vue'Button.intall = function (vue) { vue.component(Button.name, Button)}export default Button所有组件输出编写所有组件的输出就是将所有组件暴露出去,并加上一个对所有组件的install方法。其中if(window && window.Vue) install(window.Vue)是用来实现script标签引入的方式的。 import Input from 'src/cmps/input/index.js'import Toast from 'src/cmps/toast/index.js'import Button from 'src/cmps/button/index.js'const cmps = [ Input, Toast, Button]const install = vue => { cmps.map(cmp => { vue.component(cmp.name, cmp) })}if(window && window.Vue) install(window.Vue)export default { install, Input, Toast, Button}组件打包全量加载的打包全量加载的打包首先是把vue-cli生成的webpack文件改一下打包的出入口文件和路径就行了。为了方便之后的按需加载的打包,出口文件我的路径放在了lib目录下。为了实现npm包、script标签等引入形式,libraryTarget选择了umd模式。library是npm包引入时的名称。entry的写法是我为了用dev在本地测试组件是否可用而写的。externals是为了去除在组件库和实际项目中会重复的库,比如vue entry: ENV == 'dev'? path.resolve(__dirname, './src/main.js'): path.resolve(__dirname, './index.js'),output: { path: path.resolve(__dirname, './lib'), publicPath: '/dist/', filename: 'input-ui.js', library: 'input-ui', libraryExport: 'default', libraryTarget: 'umd'},externals: { vue: 'vue'}package.json中需要加入对主入口的说明 ...

June 24, 2019 · 1 min · jiezi

一个webpack构建速度优化误区

问题描述项目中使用了一个npm包a。前几天一直用得好好的,突然某次拉了别的分支代码后,就出Bug了。 第一反应是别人把这个包的版本变了。查看了下项目的package.json、package-lock.json文件,该模块和依赖模块的信息并没有改变,node_modules/a中的版本信息也和package.json中的对应。 一下子没了头绪,只好到node_modules中去调试一下。 TL;DR;拉到最后看总结 XD node_modules目录结构项目中node_modules目录如下: node_modules│└───a│ │ index.js| | ...│ ││ └───node_modules│ │ ...│ └───c| | index.js| | ...│ └───c │ index.js │ ...从该目录结构中可以发现,模块a的目录下还有一个node_modules目录,这个目录里放的是模块a的依赖。眼尖的同学可能发现了,项目本身的node_modules目录和a模块的node_modules目录中都有安装了模块c。这是为什么呢? 原因有2个: 项目直接依赖了模块c项目没有直接依赖模块c,但是项目直接依赖的模块b中依赖了模块c,并且和a中依赖的模块c版本不兼容。我们的项目中并没有直接引用模块c,所以是第二种情况。 npm的模块安装机制本节主要解释为什么项目没有直接依赖模块c,却会把c安装在项目的node_modules目录下。不感兴趣的同学可以直接跳过。 假设项目依赖了模块a和模块b,模块a依赖模块c的1.0.0版本,模块b依赖模块c的2.0.0版本。 npm2在npm2的时候,使用嵌套的方式来安装模块,c模块分别被安装到a和b模块的node_modules目录中。 这种方式虽然简单,但是却会导致node_modules中存在大量相同的模块。想象一下,如果模块a和模块依赖的模块c都是1.0.0版本,使用这种方式就会产生冗余的模块。 npm3到npm3的时候,npm2中产生冗余模块的情况得到改善。npm安装模块时会尽量把模块安装到最外层的node_modules目录中,让模块能够尽量被复用。 安装模块时,如果外层node_modules目录中没有同名模块,就将其安装到最外层ndoe_modules目录中如果外层node_modules目录中已经存在了同名模块,并且版本兼容,则不再安装(使用时直接使用外层模块)如果外层node_modules目录中已经存在了同名模块,并且版本不兼容,则安装在父模块的node_modules目录中上述情况的安装模块如图 引用了错误的模块到node_modules/a/node_modules/c/index.js中加了一些log,发现居然没执行!? 到这一步,要么是log的位置没写对,要么是没有引入这个模块。确认了webpack配置中的resolve.mainFields属性和模块c的package.json文件信息后,排除了第一种可能。 Tips: resolve.mainFields属性用来告诉webpack,引入一个npm模块时,如何找到这个模块的入口。 这时候已经有点懵了,引用模块时不是先从当前目录下的node_modules目录中开始一级一级向上查到吗?说到向上查找,那便到上一级的node_modules目录中去试一试。 果然!引用的是最外层node_modules中的模块c! 难道webpack查找模块的方式和Node.js不一样吗?还是因为webpack的某些配置导致的? 使用如下webpack配置来构建,发现并没有存在上述问题。 const path = require('path')module.exports = { entry: './src/index.js', output: { filename: 'main.js', path: path.resolve(__dirname, './dist/js') },};那接下来只要排查到底是哪些webpack配置影响到模块检索。查看项目中的webpack配置,和模块检索相关的只有resolve属性。 const config = { resolve: { modules: [ path.resolve(projectDir, 'src'), path.resolve(projectDir, 'node_modules'), path.resolve(imtPath, 'node_modules'), ], // es tree-shaking mainFields: ['jsnext:main', 'browser', 'main'], alias: {}, extensions: ['.jsx', '.js'], }}所幸配置不多,对着webpack文档查一下,很快便找到了问题:resolve.modules中使用了绝对路径。以下为webpack文档原文: ...

June 23, 2019 · 1 min · jiezi

webpack426的详细配置包含babel-eslint-postcss-及各种所需loader内含大量注释

github地址:https://github.com/qianxiaoni...内含详尽注释欢迎大家star或者fork呀~目录结构completeDemo 我的完整项目democompleteDemo 我的完整项目demobuild webpack构建文件(主要包含dll, copyWebpackPlugin, eslint, babel, less, HtmlWebpackPlugin, webpack-dev-server, hmr, CleanWebpackPlugin, webpack-merge, MiniCssExtractPlugin这些配置)src 生产文件 images 图片文件夹locales 国际化目录entry.js 入口函数index.less 样式文件static 静态资源.eslintrc.js eslint配置文件babel.config.js babel配置文件fav.ico icoindex.ejs webpack HtmlWebpackPlugin模板postcss.config.js postcss配置文件guidingDemo 官网指引demo

June 23, 2019 · 1 min · jiezi

整理了一下angularJs的webpack模板

github地址:https://github.com/qianxiaoni... 欢迎大家star或者fork呀~目录结构src/ components/ 组件 config/ dict.js 一个全局变量的run方法 router.js 路由表 validation.js 'angular-validation'的config配置 controllers/ 控制器 data/ 数据mock文件 directives/ 指令 filters/ 过滤器 image/ 图片 pages/ 页面 services/ 服务(公共方法) app.js 入口函数 common.less 公共样式文件 index.html html模板文件

June 23, 2019 · 1 min · jiezi

整理了一下react1670的webpack模板

基本上react需要方法和依赖的库都引配好了。github地址:https://github.com/qianxiaoni... 欢迎大家star或者fork呀~template-antDesign-sass-react16.7.0目录结构build/ 生成目录public/ 静态资源目录,create-react-app会直接把这里的东西起在服务根目录src/ assets/ 资源文件夹,如图片 components/ 组件 ReactSlotPra 弹窗组件,引用父组件传入的slot数据 ReduxSon redux的修改 Son 事件总线的发射 config/ 参数文件夹 pages/ 页面文件夹 Home 1.react中input的写法 2.react中组件slot的实现方式 News react中组件slot的实现方式 Product 嵌套路由的实现 ParentSonTransmit 1.父子通讯的方式 2.事件总线的监听与销毁 ReduxExperience redux的引用 HocPra 使用hoc高阶组件的公共方法 HttpPra 1.axios请求试验 2.引入antd库 redux/ redux文件夹 router/ router配置 structures/ 结构组件 utils/ events.js 事件总线模块 hoc.js hoc高阶组件(也可以写一些公共的东西,用来替代mixins) http.js http请求和antd的loading,message的结合封装 urls.js 接口地址的统一管理 utils.js 公共方法,工具函数 AppNote.js 笔记文件 index.js 入口文件 index.scss 公共样式config-overrides.js customize-cra对create-react-app的webpack的可配置,如为了antd配置了babel-plugin-importjsconfig.json create-react-app的配置文件,现在只配了项目资源可以绝对路径package.json proxy设置的地方

June 23, 2019 · 1 min · jiezi

如何用SAP-WebIDE的Fiori创建向导基于ABAP-OData-service快速创建UI5应用

如果我们手上已经有可以正常工作的OData服务,无论位于ABAP on-premise系统还是public上的internet OData service,都可以用SAP WebIDE里的Fiori创建向导,几分钟之内轻松创建出可以持续开发的UI5应用。 打开SAP云平台上的WebIDE,New->Project from Template: 选择Master Detail风格的Fiori应用: 这里就要指定这个UI5应用消费的OData服务url了。下拉菜单里看到的是一个我在SAP云平台创建的Destination,指向on premise系统: url路径选择/sap/opu/odata/sap/CRM_OPPORTUNITY,做过CRM的朋友们会知道这个路径指向的是CRM ABAP里的OData服务CRM_OPPORTUNITY: 点击Test,会解析出OData服务的metadata,然后可以点Next按钮: 点了Next之后,需要指定Master list和detail视图里重要字段的绑定路径。这些字段的说明在上图右边的缩略图里有展示。 点finish后,应用成功创建。执行应用: 最后渲染的应用如下: 至此我们没有编写一行代码,就得到了一个可以工作的master-detail风格的Fiori应用。 压缩过后webIDE自动生成的JavaScript总共代码也不过500多行: 要获取更多Jerry的原创文章,请关注公众号"汪子熙":

June 23, 2019 · 1 min · jiezi

vuewebpack40-生产环境手动一步一步配置-持续更新中

vue-webpack介绍 vue+webpack 手动搭建过程,熟悉 webpack 的配置,loader&插件的使用 介绍目标:熟悉 webpack 的配置,loader&插件的使用 通常新建 vue 项目都使用 vue-cli 脚手架,其实对于 webpack 的配置是一知半解,当需要升级 webpack 或者优化项目配置时,就显得很无力。通过手动搭建 webpack 可以对 webpack 有更深入的了解,当我们使用其他模块管理器时(eg:rollup,gulp),也不会那么生疏。 关于 dependencies 和 devDependencies通过 NODE_ENV=developement 或 NODE_ENV=production 指定开发还是生产环境 devDependencies 是只会在开发环境下依赖的模块,生产环境不会被打入包内。 而 dependencies 依赖的包不仅开发环境能使用,生产环境也能使用。其实这句话是重点,按照这个观念很容易决定安装模块时是使用--save 还是--save-dev。 项目包版本项目地址 "dependencies": { "@xunlei/vue-lazy-component": "^1.1.3", "echarts": "^4.2.1", "element-resize-event": "^3.0.3", "element-ui": "^2.7.2", "file-loader": "^4.0.0", "html-loader": "^0.5.5", "html-webpack-plugin": "^3.2.0", "intersection-observer": "^0.7.0", "lodash": "^4.17.11", "url-loader": "^2.0.0", "vue": "^2.6.10", "webpack": "^4.34.0" }遇到的配置错误1.vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config.解决办法:Vue-loader 在 15.*之后的版本都是 vue-loader 的使用都是需要伴生 VueLoaderPlugin 的 ...

June 21, 2019 · 5 min · jiezi

webpack基础

安装npm install -g webpack webpack-cli快速开始最新的 webpack 支持零配置使用,默认入口为当前目录下的 src 中的 index.js 文件,默认打包输出的目录为 dist 目录,默认打包模式 mode 为 development先建一个文件夹,如 webpack-testwebpack-test 文件下新建一个 src 目录,再src 下新建一个 index.js 文件终端进入 webpack-test 目录,运行 webpackwebpack 会在 webpack-test 目录下生成一个 dist 目录。配置项说明在 webpack-test 目录下新建一个 webpack.config.js ,返回的是一个配置对象。 字段名可选值说明mode"development" \"production" \"none"表示打包类型,为 production 时会压缩代码entry字符串 \对象打包入口文件output对象配置打包后文件夹和格式化文件名等entry 配置入口文件在 src 目录下新建 a.js ,b.js// 单一入口module.exports = { entry:'./src/a.js'}// 多入口module.exports = { entry:{ a:'./src/a.js', b:'./src/b.js' }}在多入口时,会在 dist 目录下打包 a.js 和 b.js outputfilename 打包之后的文件夹名// 单入口情景module.exports = { entry:'./src/a.js', output:{ filename:'[name].[hash:7].js' }}// 打包后类似 main.abdfa13.js// 多入口情景module.exports = { entry:{ a:'./src/a.js', b:'./src/b.js' }, output:{ filename:'[name].[hash:7].js' }}// 打包后生成类似 a.abdfa13.js , b.abdfa13.js在配置文件中,有几个可用的参数,如 hash 当前打包随机字符串,name对应 entry 中的属性名(但单入口默认为main),ext 对应 loader 中的文件后缀名。path 打包生成的目标文件夹,必须为一个绝对地址const path = require('path');module.exports = { entry:'./src/a.js', output:{ filename:'[name].[hash:7].js', path:path.resolve(__dirname,'./dist') }}publicPath,针对打包后的项目不在服务器的根目录访问,需要加上路径的情况。保证资源访问地址正确。主要体现在页面中引用绝对地址的图片,和 webpackPlugin 注入资源地址的时候。比如最后项目访问路径为:https://haokur.com/webpack-test/index.html ,则需要配置 ...

June 21, 2019 · 1 min · jiezi

webpack开发环境配置

日常吐槽经过不断的调整和测试,关于 react 的 webpack 配置终于新鲜出炉。本次的重点主要集中在开发环境上,生产环境则是使用 webpack 的 production 默认模式。 本次配置主要有: eslint+prettier;optimization.splitChunks;happypack;DllReferencePlugin & DllPlugin;...文档的重要性讲真,对于初次接触 webpack 的同学,怕的可能不是 webpack 的配置,而是长长的 package.json。依赖那么多,你怎么就知道需要哪些依赖呢。不开玩笑,我还真知道。webpack 的依赖主要是一些 loader 和 plugins。我们知道单页面引用被打包后,原有的结构基本上不复存在了。而之前引用的图片或字体资源还按照之前的路径查找,肯定是找不到的。那么我们就需要转换工具(顺便转换资源)—— url-loader|file-loader。大多数人写样式时,喜欢使用 css、less、sass。这时也会有对应的工具 style-loader, css-loader, less-loader。想要使用 JavaScript 新特性或处理兼容性,就用 babel-loader。以上这些基本上可以应付一些简单的项目。可实际上呢? 我信你个鬼,你这个糟老头坏的很!看文档啊,看官方介绍啊。本次也是通过看 babel 文档,和一些依赖文档来配置 webpack 的,全程无压力,而且很正宗。所以,文档很重要。 eslint+prettier如果时团队合作,代码规范是很重要的。可以通过 eslint+prettier 规范。这两个工具各有侧重点,不过官网也提供了两者结合的方案。详细介绍见官网。我个人不习惯创建太多的配置文件,所以都放在了 package.json 文件中。 // webpack.common.js{ enforce: "pre", test: /\.m?jsx?$/, exclude: /node_modules/, loader: "eslint-loader", options: { fix: true, cache: true, formatter: require("eslint-friendly-formatter"), }},"eslintConfig": { "parser": "babel-eslint", "env": { "browser": true, "es6": true, "node": true }, "parserOptions": { "ecmaVersion": 6, "sourceType": "module" }, "extends": [ "plugin:prettier/recommended" ]},"prettier": { "singleQuote": true, "semi": true},开发环境开发环境没什么好说的了,简单易配置,官网很详细。 ...

June 21, 2019 · 2 min · jiezi

vuecli3下配置IE浏览器兼容性

最近,在重构公司官网,需要兼容ie9/10/11,使用vue-cli构建项目。 在查询如何兼容ie时,首先是查看vue cli官网,浏览器兼容性,感觉官网说的不是太明晰(小白一枚,实在不太懂),然后就直接百度了,网上方法基本类似,都是用 browserslist,babel-polyfill等,只是具体步骤有差异,不过 都没有解决本人问题。经过层层查询,逐步对vue-cli 原理了解后,网上查询方法结合本人理解,将问题解决,在此记录下。 先说步骤,然后说一些自己浅显理解。 一.解决步骤1.配置browserslist配置这一项,有两个途径,一是 在 package.json文件中,添加browserslist字段;二是 在项目根目录,创建一个.browserslistrc文件,两种途径。这两种方法不能同时配置,不然运行serve命令会报错。 先说package.json中配置,网上很多如下方法: "browserslist": [ "> 1%", "last 4 versions" ]本人依此配置,报错!然后按照另外一种配置,如下: "browserslist": [ "ie 11" ]成功! 额外贴出.browserslistrc方法配置方式(只是列出书写方式,代码有效性,按上面来): > 1%last 4 versions2.安装babel-polyfill依赖这个简单,直接 npm i babel-polyfill --save-dev即可 3.引入babel-polyfill依赖 这一步是关键,网上查询很多,在main.js中,import babel-polyfill引入,本人测试后无效。 具体引入是在vue.config.js中configureWebpack字段中,具体: configureWebpack: config => { config.entry.app = ["babel-polyfill", "./src/main.js"]; }即在webpack入口配置中,加入babel-polyfill。至此,在ie下,兼容es6就解决了! 二.自己的理解上面把问题解决了,再将自己解决过程中的理解梳理下。 1.首先上面的解决步骤,仅仅适用于源码(/src),对依赖包无效。当需要对依赖包做兼容转译时,就需要用到官网中Polyfill部分内容了 2.vue-cli中webpack配置文件是在node_modules中的,没有直接在根目录,要想配置webpack,需要在vue.config.js中configureWebpack字段或者chainWebpack配置。具体如下: module.exports = { configureWebpack: { resolve: { alias: { querystring: 'querystring-browser' } } }}module.exports = { chainWebpack: config => { config.resolve.alias.set('querystring', 'querystring-browser') }}解决过程中,查询的相关资料1.Vue 兼容 ie9 的全面解决方案2.Vue CLI 3 浏览器兼容性配置3.Editing webpack.config.js when using vue-cli 3 ...

June 19, 2019 · 1 min · jiezi

手摸手带你用vue实现后台管理权限系统及顶栏三级菜单显示

手摸手,带你用vue实现后台管理权限系统及顶栏三级菜单显示 效果演示地址项目demo展示 重要功能总结权限功能的实现权限路由思路:根据用户登录的roles信息与路由中配置的roles信息进行比较过滤,生成可以访问的路由表,并通过router.addRoutes(store.getters.addRouters)动态添加可访问权限路由表,从而实现左侧和顶栏菜单的展示。 实现步骤: 1.在router/index.js中,给相应的菜单设置默认的roles信息; 如下:给"权限设置"菜单设置的权限为:meta:{roles: ['admin', 'editor']},及不同的角色都可以看到; 给其子菜单"页面权限",设置权限为:meta:{roles: ['admin']},及表示只有"admin"可以看到该菜单; 给其子菜单"按钮权限"设置权限为:meta:{roles: ['editor']},及表示只有"editor"可以看到该菜单。 2.通过router.beforeEach()和router.afterEach()进行路由过滤和权限拦截; 代码如下: // permission judge functionfunction hasPermission(roles, permissionRoles) { if (roles.indexOf('admin') >= 0) return true // admin permission passed directly if (!permissionRoles) return true return roles.some(role => permissionRoles.indexOf(role) >= 0)}const whiteList = ['/login'] // 不重定向白名单router.beforeEach((to, from, next) => { NProgress.start() // 设置浏览器头部标题 const browserHeaderTitle = to.meta.title store.commit('SET_BROWSERHEADERTITLE', { browserHeaderTitle: browserHeaderTitle }) // 点击登录时,拿到了token并存入了vuex; if (getToken()) { /* has token*/ if (store.getters.isLock && to.path !== '/lock') { next({ path: '/lock' }) NProgress.done() } else if (to.path === '/login') { next({ path: '/' }) // 会匹配到path:'',后面的path:'*'还没有生成; NProgress.done() } else { if (store.getters.roles.length === 0) { store.dispatch('GetInfo').then(res => { // 拉取用户信息 const roles = res.roles store.dispatch('GenerateRoutes', { roles }).then(() => { // 根据roles权限生成可访问的路由表 router.addRoutes(store.getters.addRouters) // 动态添加可访问权限路由表 next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 }) }).catch((err) => { store.dispatch('FedLogOut').then(() => { Message.error(err || 'Verification failed, please login again') next({ path: '/' }) }) }) } else { // 没有动态改变权限的需求可直接next() 删除下方权限判断 ↓ if (hasPermission(store.getters.roles, to.meta.roles)) { next()// } else { next({ path: '/401', replace: true, query: { noGoBack: true }}) } } } } else { if (whiteList.indexOf(to.path) !== -1) { next() } else { // 点击退出时,会定位到这里 next('/login') NProgress.done() } }})router.afterEach(() => { NProgress.done() // 结束Progress setTimeout(() => { const browserHeaderTitle = store.getters.browserHeaderTitle setTitle(browserHeaderTitle) }, 0)})用户点击登录之后的业务逻辑分析: ...

June 19, 2019 · 3 min · jiezi

createreactapp-源码学习上

原文地址Nealyang/personalBlog前言对于前端工程构建,很多公司、BU 都有自己的一套构建体系,比如我们正在使用的 def,或者 vue-cli 或者 create-react-app,由于笔者最近一直想搭建一个个人网站,秉持着呼吸不停,折腾不止的原则,编码的过程中,还是不想太过于枯燥。在 coding 之前,搭建自己的项目架构的时候,突然想,为什么之前搭建过很多的项目架构不能直接拿来用,却还是要从 0 到 1 的去写 webpack 去下载相关配置呢?遂!学习下 create-react-app 源码,然后自己搞一套吧~ create-react-app 源码代码的入口在 packages/create-react-app/index.js下,核心代码在createReactApp.js中,虽然有大概 900+行代码,但是删除注释和一些友好提示啥的大概核心代码也就六百多行吧,我们直接来看 index.js index.js 的代码非常的简单,其实就是对 node 的版本做了一下校验,如果版本号低于 8,就退出应用程序,否则直接进入到核心文件中,createReactApp.js中 createReactApp.jscreateReactApp 的功能也非常简单其实,大概流程: 命令初始化,比如自定义create-react-app --info 的输出等判断是否输入项目名称,如果有,则根据参数去跑安装,如果没有,给提示,然后退出程序修改 package.json拷贝 react-script 下的模板文件准备工作:配置 vscode 的 debug 文件 { "type": "node", "request": "launch", "name": "CreateReactApp", "program": "${workspaceFolder}/packages/create-react-app/index.js", "args": [ "study-create-react-app-source" ] }, { "type": "node", "request": "launch", "name": "CreateReactAppNoArgs", "program": "${workspaceFolder}/packages/create-react-app/index.js" }, { "type": "node", "request": "launch", "name": "CreateReactAppTs", "program": "${workspaceFolder}/packages/create-react-app/index.js", "args": [ "study-create-react-app-source-ts --typescript" ] }这里我们添加三种环境,其实就是 create-react-app 的不同种使用方式 ...

June 18, 2019 · 7 min · jiezi

译使用-ReactTypeScript-和-Webpack-开始一个项目

原文:Getting Started with React TypeScript and Webpack作者:Grant译者:博轩我会通过这篇文章,为大家讲述,如何使用 React,TypeScript 和 Webpack 来构建一个项目。 开始这是一篇关于如何使用 React,TypeScript 和 Webpack 来构建一个非常基础的项目的教程。您可以继续阅读,或者直接在 github 上面查看示例代码。 译注:create-react-app 已经提供了关于 TypeScript 开箱即用的支持,也可以使用 react-scripts 或者 react-app-rewired 完成对于 Webpack 配置的扩展。本文也只是聊一聊如何从 0 构建一个项目,大家了解一下就好 ????设置项目为你的项目创建一个文件夹mkdir your-folder-name && cd your-folder-name && npm init --yes为项目安装 React 和 React-DOM 的依赖npm install react && npm install react-dom根据我们的项目配置需求,我们需要 TypeScriptnpm install typescript --save-dev安装 React 和 React-DOM 的类型npm install @types/react --save-dev && npm install @types/react-dom --save-dev接下来,我们可以初始化我们的 TypeScript 项目。您应该 tsconfig.json 文件被创建。tsc --init打开 tsconfig.json,之后添加一个 include数组 compilerOptions 。这将告诉 TypeScript 在哪找到我们的代码。{ "compilerOptions": { }, "include":[ "./src/**/*" ]}现在创建一个 src 文件夹,并在里面创建一个 App.ts 文件。export class App{ constructor() { console.log("Hello app!"); }}测试 TypeScript 是通过 tsc 命令在终端中运行编译。如果成功,您应该看到 src 文件夹下面出现 App.js 的文件。完成后,我们删除 .js 文件,继续后续操作。让 TypeScript 和 React 一起工作现在,让我们看看 TypeScript 是否可以编译 React 文件。 ...

June 15, 2019 · 3 min · jiezi

webpack-配置多页面应用的一次尝试

最近有一个项目,考虑到要进行 SEO,所以要做成多页面应用。为了保证开发速度和开发效率,所以决定使用 webpack 做一套模块化配置方案。下面主要针对一些重要的点提供思路,并不作详解。完整的代码,我会放在 github(项目地址)上供大家参考,如果有优化的地方,请在评论区指点出来,。目录|-- build webpack 配置| |-- utils.js 处理 webpack 配置的公共方法| |-- webpack.base.conf.js 公共配置 | |-- webpack.dev.conf.js 开发环境配置| |-- webapck.prod.conf.js 生产环境配置| |-- webpack.rules.conf.js 文件处理规则|-- dist 存放变异后文件|-- ||-- src 源文件| |-- assets| |-- pages | | |-- index 首页| | | |-- index.html 首页模板| | | |-- index.js 首页入口文件| htmlarrary.js 页面配置文件多页面多页面,首先最重要的就是处理多个 html 模板和对应的多个入口文件。 html 模板在项目根目录创建一个 htmlarrary.js,用来存储页面配置: // htmlarrary.jsmodule.exports = [ { _html: 'index', title: '首页', chunks: ['index', 'manifest', 'vendors'] // 页面用到的vendor模块 }, { _html: 'login', title: '登录', chunks: ['login'] }]然后在 /build/utils.js 创建 getHtmlArray 方法,用来自动生成多个模板的配置: ...

June 15, 2019 · 3 min · jiezi

从webpack初始化到配置babel环境

一、新建项目文件夹,在文件夹打开终端运行npm init,一直回车二、安装babel所需要的包 npm install --save-dev @babel/core @babel/cli @babel/preset-envnpm install --save @babel/polyfill三、根目录下新建babel.config.js,填入: const presets = [ [ "@babel/env", { targets: { edge: "17", firefox: "60", chrome: "67", safari: "11.1", }, useBuiltIns: "usage", }, ],];module.exports = { presets };四、根目录下新建webpack.config.js,填入: const path = require('path');module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, mode: 'development'};五、执行,安装webpack,根据提示安装webpack-cli npm install webpack --save-dev 六、修改packge.json,script填入 "build": "webpack"七、命令行运行,npm run build

June 13, 2019 · 1 min · jiezi

webpack-四个核心概念之Entry

因为webpack是基于nodejs的一款工具,所以在学习过程中涉及到的nodejs知识也会进行解释进行发散性拓展。webpack中文文档一、module.exports module.exports = { entry: './path/to/my/entry/file.js' };exports 变量是在模块的文件级作用域内可用的,且在模块执行之前赋值给 module.exports在nodejs中,提供了exports 和 require 两个对象,其中 exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。而在exports抛出的接口中,如果你希望你的模块就想为一个特别的对象类型,请使用module.exports;如果希望模块成为一个传统的模块实例,请使用exports.xx方法;module.exports才是真正的接口,exports只不过是它的一个辅助工具。最终返回给调用的是module.exports而不是exports。这里引用nodejs官网的一个例子 function require(/* ... */) { const module = { exports: {} }; ((module, exports) => {`请输入代码` // 模块代码在这。在这个例子中,定义了一个函数。 function someFunc() {} exports = someFunc;//也就是说你单独给exports赋值时候exports不属于module了是一个单独的变量 // 此时,exports 不再是一个 module.exports 的快捷方式, // 且这个模块依然导出一个空的默认对象。 module.exports = someFunc;//这里导出的函数是挂在module里的所以会被导入 // 此时,该模块导出 someFunc,而不是默认对象。 })(module, module.exports); return module.exports;//这里是这句话的解释 (最终返回给调用的是module.exports而不是exports) }二、entryentry入口起点,entry所配置的文件路径所指向的文件为项目的入口文件也就是内部依赖的开始会根据入口文件去逐层加载依赖。Chunk 和打包时入口文件配置有关如果 entry 是一个 string 或 array ,就只会生成一个 Chunk,这时 Chunk 的名称是 main,如果 entry 是一个 object ,就可能会出现多个 Chunk,这时 Chunk 的名称是 object 键值对里键的名称。 ...

June 12, 2019 · 1 min · jiezi

为什么我要构建这个脚手架

本文不是什么技术性介绍文章,准确地说算是自己的成长记录吧。刚参加工作时,组里使用的脚手架是由 leader 使用 webpack, gulp 搭建的多页面应用脚手架 fex。当时只需知道怎么使用就行了,不过为了能更好地工作,对 fex 怎么构建一直很好奇,也一直关注相关的技术栈。经过一年多磨练后,对 fex 怎么搭建的有了个大概地认识。常言道:"没有对比就没有伤害"。 在使用 vue-cli 构建第一个 vue 项目后,对脚手架构建有了个全新的认识。发现 fex 存在很多不足: 在打包时,只对 JavaScript 和 CSS 脚本文件进行打包压缩处理。不能对资源文件(如 img,字体等)进行依赖处理。导致在打包时: 不能按需打包(即实际用到资源,才将其进行打包)不能进行 MD5 处理不能输出压缩版的 html手动注入 JavaScript 和 CSS 脚本文件,如果需要做优化,会很不方便,特别在多页面情况下。dev 与 build 使用不同的技术方案,增加定制的成本。基于 nodemon 对开发目录进行 watch,当执行修改操作时,会重启整个服务。会存在重启服务耗时比较长的情况,导致刷新页面出现空页面的情况,开发体验不是很好。缺少 code-splitting、HMR、端口检测、Babel 等功能。当然,fex 也有自己的优点。基于自建服务提供前后端复用模板功能。前端后端使用相同的模板语言,前端拼接的模板可以直接输出给后端使用。 第二年年初,组里项目不是太多,刚好有时间折腾一下,于是决定构建一个全新的脚手架 fes。为了尝试一些新东西,在技术栈上,都使用了当时最新的技术框架 webpack4、koa2、babel6 来搭建。为了了解 webpack 如何工作,对 webpack 就做了 8 次调试,才稍微对 webpack 整个架构有个初步认识。 singsong: 在真正去了解 webpack 时,才知道它有多复杂。当然也参考了网上一些大神分享关于 webpack 源码分析的文章。反正整个过程还是挺熬心的????同时,还对 koa2、babel6 做了相关的研究。附一张 koa2 分析图吧????: 为了提高 fes 开发体验,除了继承 fex 的模板复用功能外,还集成了 vue-cli 中不错的功能。 ...

June 11, 2019 · 5 min · jiezi

vue-proxyTable-配置代理解决跨域

vue + webpack 构建的项目解决浏览器跨域问题在 config/index.js 中配置 proxyTable 代理,如下图所示: proxyTable: { // 配置代理 '/api': { // 匹配所有以 '/api' 开头的请求路径 target: 'http://localhost:4000', // 代理目标的基础路径 changeOrigin: true, // 支持跨域 pathRewrite: { // 重写路径: 去掉路径中开头的'/api' '^/api': '' } }},

June 11, 2019 · 1 min · jiezi

packagejson-中-你还不清楚的-browsermodulemain-字段优先级

browser VS module VS main前端开发中使用到 npm 包那可算是家常便饭,而使用到 npm 包总免不了接触到 package.json 包配置文件。 那么这里就有一个问题,当我们在不同环境下 import 一个 npm 包时,到底加载的是 npm 包的哪个文件? 老司机们很快地给出答案:main 字段中指定的文件。 然而我们清楚 npm 包其实又分为: 只允许在客户端使用的,只允许造服务端使用的,浏览器/服务端都可以使用。如果我们需要开发一个 npm 包同时兼容支持 web端 和 server 端,需要在不同环境下加载npm包不同的入口文件,显然一个 main 字段已经不能够满足我们的需求,这就衍生出来了 module 与 browser 字段。 本文就来说下 这几个字段的使用场景,以及同时存在这几个字段时,他们之间的优先级。 文件优先级在说 package.json 之前,先说下文件优先级 由于我们使用的模块规范有 ESM 和 commonJS 两种,为了能在 node 环境下原生执行 ESM 规范的脚本文件,.mjs 文件就应运而生。 当存在 index.mjs 和 index.js 这种同名不同后缀的文件时,import './index' 或者 require('./index') 是会优先加载 index.mjs 文件的。 也就是说,优先级 mjs > js ...

June 11, 2019 · 2 min · jiezi

webpack4322系列教程03-devtool

简介 devtool选项用于控制是否需要生成source map,以及如何生成source map。源码地址 什么是source map? source map 一个存储源代码与编译代码对应位置的映射信息文件,它是专门给调试器准备的,它主要用于debug,目前我所知的只有Google Dev Tools 和 Fire Fox Debugger 支持source map。 Google Dev Tools 可以通过以下方式打开JavaScript的source map 和 CSS的source map: source map主要用于将压缩混淆后的JavaScript代码和CSS代码映射到源码中,方便debug调试。更多关于source map的知识,大家可以参考阮一峰大神的文章:JavaScript Source Map 详解 演示 最新的webpack官网中一共有13种devtool可选模式,不同的模式打包输出的代码和source map以及构建的速度都不一样,下面我演示几种比较常用的devtool模式。 eval 表示把每一个模块文件都转换为字符串,并且在每一个模块代码的尾部添加 //# sourceURL=webpack:/// 文件名.js,并使用eval执行。 1、编写入口文件和依赖代码 2、编写webpack配置 & 启动webpack const webpack = require('webpack');// 创建编译器对象const compiler = webpack({ mode: 'development', devtool: 'eval'});// 启动webpackcompiler.run((err, stats) => { if (err) { console.error(err); return; } // 输出编译成功信息 console.log(stats.toString({ colors: true }));});webpack运行结果: ...

June 9, 2019 · 1 min · jiezi

JAVA前后端分离开发环境搭建详细教程JeecgBoot快速开发平台

目录索引: 后端开发工具前端开发工具Nodejs镜像WebStorm入门配置 JeecgBoot采用前后端分离的架构,官方推荐开发工具 前端开发: Webstrom 或者 IDEA 后端开发: Eclipse安装lombok插件 或者 IDEA 开发工具下载:https://pan.baidu.com/s/1tZmFuViGz5IwHhzmA-FN6A 提取码:frya 后端开发工具序号工具参考1eclipse安装lombok插件https://blog.csdn.net/qq_2564...2Eclipse自定义皮肤主题https://blog.csdn.net/StillOn...3Eclipse常用快捷键https://blog.csdn.net/zhangda...前端开发工具序号工具描述参考1Nodejs/Npm安装JavaScript运行环境,此处使用到它的包管理器npmhttp://www.jianshu.com/p/03a7...2Yarn安装下载包工具https://yarnpkg.com/zh-Hans/d...3WebStorm安装与使用WEB前端开发工具https://blog.csdn.net/u011781...配置Nodejs镜像npm config set registry https://registry.npm.taobao.org --globalnpm config set disturl https://npm.taobao.org/dist --globalyarn config set registry https://registry.npm.taobao.org --globalyarn config set disturl https://npm.taobao.org/dist --globalWebStorm-2018.1.3 开发工具入门配置序号标题链接1WebStorm安装与使用https://blog.csdn.net/u011781...2webstorm 2018 激活破解https://blog.csdn.net/q358591...3修改webstorm主题https://blog.csdn.net/master_...4Webstorm切换快捷键风格(Webstorm快捷键与eclipse对比介绍)https://blog.csdn.net/gsying1...5WebStorm SVN用法https://blog.csdn.net/hysh_ke...6‘svn’不是内部或外部命令问题解决https://blog.csdn.net/mitea90...7设置webstorm的vue新建文件模板(后面篇章)https://blog.csdn.net/diligen...8WebStorm卡顿拉取svn慢解决https://blog.csdn.net/WYA1993...前端Webstorm开发界面:后端Eclipse开发界面:

June 8, 2019 · 1 min · jiezi

Vue项目总结webpack常规打包优化方案

由于新建项目发版打包时间大概需要30分钟,发版时严重拖慢下班时间,所以特意查看了相关文档来优化打包速度,争取早点下班,^_^。 分析打包文件要优化,先分析。我们先要知道到底是哪里拖慢我们的打包速度呢? 打包后生成文件分析可以利用webpack-bundle-analyzer插件来分析我们打包后生成的文件 安装npm i webpack-bundle-analyzer -D使用修改webpack.prod.conf.js文件 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin// 构建完成后,浏览器会自动打开localhost:8080webpackConfig.plugins.push( new BundleAnalyzerPlugin({ analyzerPort: 8080, generateStatsFile: false })) 通过图片可以看到打包后文件的具体信息 打包进度条显示,可以查看到打包进度百分比simple-progress-webpack-plugin可以显示打包百分比 安装npm i simple-progress-webpack-plugin -D使用修改webpack.prod.conf.js文件 const SimpleProgressWebpackPlugin = require( 'simple-progress-webpack-plugin' )... plugins: [ new SimpleProgressWebpackPlugin() ]...效果如下: 资源与依赖包的控制通过上面进度可以看到,打包过程中,卡顿在压缩的地方过长,当项目越来越臃肿的时候,我们要需要对项目静态资源以及依赖包进行整理, 图片过大的可以压缩,这里推荐一个还不错的压缩链接项目中没有使用的依赖可以删除,可以按需引用的依赖,按需引用项目里面使用ElementUI和Echarts都是全部引用挂在Vue.prototype上,现都改为按需引用。 减少文件搜索范围设置resolve.alias字段,避免打包时如果使用相对路径访问或着import文件时会层层去查找解析文件resolve: { alias: { '@': resolve('src') }}合理配置extensions扩展名resolve.extensions能够自动解析确定的扩展,但是如果extensions扩展名过多,会导致解析过程过多,所以我们要合理配置扩展名,不要过多配置扩展名,项目引用多的文件,扩展名放在前面,我司项目中多的是vue,js文件,可以只引用这两种。 resolve: { extensions: ['.vue', '.js']}loader预处理文件增加include匹配特定条件预处理各种文件时指定匹配目录后,webpack解析文件时就不会循环查找其他目录,加快解析速度。 happypack多线程执行webpack执行预处理文件时单线程的,我们可以使用happypack来多线程处理文件。 安装npm i happypack -D使用修改webpack.base.js文件 const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });module: { rules: [ { test: /\.js$/, loader: 'happypack/loader?id=babel', // 原始loader替换成`happypack/loader` include: [resolve('src')] } ]},plugins: [ new HappyPack({ // id标识 需要处理的loader id: 'babel', // loader配置和原始配置一样 loaders: [ { loader: 'babel-loader', options: { presets: ['es2015'], cacheDirectory: true } } ], threadPool: happyThreadPool })]babel-plugin-dynamic-import-node异步加载babel-plugin-dynamic-import-node插件是使import() 替换成 require 编译 ...

June 6, 2019 · 1 min · jiezi

傻傻分不清的Manifest

在前端,说到manifest,其实是有歧义的,就我了解的情况来说,manifest可以指代下列含义: html标签的manifest属性: 离线缓存(目前已被废弃)PWA: 将Web应用程序安装到设备的主屏幕wbbpack中webpack-manifest-plugin插件打包出来的manifest.json文件,用来生成一份资源清单,为后端渲染服务webpack中DLL打包时,输出的manifest.json文件,用来分析已经打包过的文件,优化打包速度和大小下面我们来一一介绍下 html属性<!DOCTYPE html><html lang="en" manifest="/tc.mymanifest"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <link rel="stylesheet" href="/theme.css"> <script src="/main.js"></script> <script src="/main2.js"></script></head><body> </body></html>浏览器解析这段html标签时,就会去访问tc.mymanifest这个文件,这是一个缓存清单文件 tc.mymanifest # v1 这是注释CACHE MANIFEST/theme.css/main.jsNETWORK:*FALLBACK:/html5/ /404.htmlCACHE MANIFEST指定需要缓存的文件,第一次下载完成以后,文件都不会再从网络请求了,即使用户不是离线状态,除非tc.mymanifest更新了,缓存清单更新之后,才会再次下载。标记了manifest的html本身也被缓存 NETWORK指定非缓存文件,所有类似资源的请求都会绕过缓存,即使用户处于离线状态,也不会读缓存 FALLBACK指定了一个后备页面,当资源无法访问时,浏览器会使用该页面。比如离线访问/html5/目录时,就会用本地的/404.html页面 缓存清单可以是任意后缀名,不过必须指定content-type属性为text/cache-manifest 那如何更新缓存?一般有以下几种方式: 用户清空浏览器缓存manifest 文件被修改(即使注释被修改)由程序来更新应用缓存需要特别注意:用户第一次访问该网页,缓存文件之后,第二次进入该页面,发现tc.mymanifest缓存清单更新了,于是会重新下载缓存文件,但是,第二次进入显示的页面仍然执行的是旧文件,下载的新文件,只会在第三次进入该页面后执行!!! 如果希望用户立即看到新内容,需要js监听更新事件,重新加载页面 window.addEventListener('load', function (e) { window.applicationCache.addEventListener('updateready', function (e) { if (window.applicationCache.status == window.applicationCache.UPDATEREADY) { // 更新缓存 // 重新加载 window.applicationCache.swapCache(); window.location.reload(); } else { } }, false);}, false);建议对tc.mymanifest缓存清单设置永不缓存 不过,manifest也有很多缺点,比如需要手动一个个填写缓存的文件,更新文件之后需要二次刷新,如果更新的资源中有一个资源更新失败了,将导致全部更新失败,将用回上一版本的缓存 HTML5规范也废弃了这个属性,因此不建议使用 PWA为了实现PWA应用添加至桌面的功能,除了要求站点支持HTTPS之外,还需要准备 manifest.json文件去配置应用的图标、名称等信息 <link rel="manifest" href="/manifest.json">{ "name" : "Minimal PWA" , "short_name" : "PWA Demo" , "display" : "standalone" , "start_url" : "/" , "theme_color" : "#313131" , "background_color" : "#313131" , "icons" : [ { "src": "images/touch/homescreen48.png", "sizes": "48x48", "type": "image/png" } ] }通过一系列配置,就可以把一个PWA像APP一样,添加一个图标到手机屏幕上,点击图标即可打开站点 ...

June 5, 2019 · 5 min · jiezi

快速搭建的webpackvue项目

快速搭建的webpack+vue项目!第一步: npm install -g @vue/cli第二步: npm install -g @vue/cli-init第三步: vue init webpack my-project会有一系列选项,询问项目名称等,可以默认(按Enter键),也可以自定义。 等待几分钟,安装成功:# Project initialization finished! 此时一个快速搭建的webpack+vue项目就构建成功啦! 下面来查看一下项目结构: tree .│ .babelrc│ .editorconfig│ .eslintignore│ .eslintrc.js│ .gitignore│ .postcssrc.js│ ii.txt│ index.html│ info.txt│ package.json│ README.md│├─build # webpack config files│ webpack.base.conf.js│ webpack.dev.conf.js│ webpack.prod.conf.js│ ...├─config│ index.js # main project config│ ...├─node_modules├─src│ │ App.vue # main app component│ │ main.js # app entry file│ ├─ assets # module assets (processed by webpack)│ │ ...│ ├─ components # ui components│ │ ...│ └─ router│ index.js│├─static # pure static assets (directly copied)└─test └─e2e │ nightwatch.conf.js │ runner.js │ ├─custom-assertions │ elementCount.js │ └─specs test.js第四步:进入项目文件: ...

June 3, 2019 · 1 min · jiezi

如何查找SAP-Fiori-launchpad-Designer的准确路径即url地址

比如我们知道在SPRO里下面这个路径的customizing activity里打开Fiori Launchpad designer: SAP Netweaver->UI technologies->SAP Fiori->Configure Launchpad content->Adding Apps to SAP Fiori Launchpad->Configure Target Mappings and Tiles->SAP Fiori Launchpad Designer, 点右键,选择Display technical info: 找到这个activity绑定的事务码为/UI2/FLPD_CUST: SE93里查到这个事务码绑定的report名称为/UI2/START_URL: 这个报表执行后的界面: Fiori Launchpad designer的准确路径可以通过调试获得,存储于变量gv_url里: 要获取更多Jerry的原创文章,请关注公众号"汪子熙":

June 1, 2019 · 1 min · jiezi

Webpack-4手工搭建深度分析

前言这是一篇关于webpack 4手工搭建重点问题的分析,webpack 3相关可以戳这里:https://github.com/Eleven90/webpack-pages-V3,这里并不试图从零手把手去堆代码,而是对其中的重点问题做稍微深入一点的解读。某些细节这里如果没有提及,项目代码里可能会有。项目地址:https://github.com/Eleven90/webpack-template为懒人准备的 webpack 配置模版,可以直接用于生产。这里单纯只做webpack打包的配置、前端工程化代码的组织等,有意抛开三大框架,从原始的H5出发去组织代码,关于React、Vue等配置并不复杂,可以在开发需要时添加。技术栈es6 + less + art-template + webpack 4普通 H5 开发中,引入组件化;引入 art-template 前端渲染引擎——目前前端模版里速度最快;配置 dev-server 调试模式,proxy 代理接口调试;配置 watch 模式,方便在生产环境中用 Charles 映射到本地文件;optimization 配置提取 runtime 代码;splitChunks 拆分代码,提取 vendor 主要缓存包,提取 common 次要缓存包;支持多页、多入口,自动扫描,可无限层级嵌套文件夹;MockJs 模拟 mock 数据;运行命令推荐使用yarn进行包管理,项目在某个时间节点被我切换到了yarn,但写文档时仍然是npm,对应变更一下即可。# 如果不熟悉或不想尝试yarn,直接npm install,然后npm run dev即可,不会有任何副作用yarn / yarn install # 安装全部依赖包yarn dev # 启动本地调试yarn dev-mock # 启动本地调试,MockJs模拟接口数据yarn dev:page-a # 启动本地调试,仅page-a页面yarn dev:page-b # 启动本地调试,仅page-b页面yarn build-dev # 打包代码,publicPath以/打头(可通过本地起服务访问build后的代码)yarn http-server # 启动http-server服务器,可用来访问yarn build-dev打包的代码yarn build-test # 打包测试环境代码yarn build # 打包生产环境代码# watch模式,移除了js、css的压缩,节省时间(watch时需要build压缩版代码,可自行修改)。yarn watch-dev # 启动watch模式,本地开发环境(通常用不上)yarn watch-test # 启动watch模式,测试环境yarn watch # 启动watch模式,生产环境# 如果你想用npm的话...(建议把yarn.lock文件也删掉)npm install # 安装全部依赖包npm run dev # 启动本地调试npm run dev-mock # 启动本地调试,MockJs模拟接口数据npm run dev:page-a # 启动本地调试,仅page-a页面npm run dev:page-b # 启动本地调试,仅page-b页面npm run build-dev # 打包代码,publicPath以/打头(可通过本地起服务访问build后的代码)npm run http-server # 启动http-server服务器,可用来访问npm run build-dev打包的代码npm run build-test # 打包测试环境代码npm run build # 打包生产环境代码# watch模式,移除了js、css的压缩,节省时间(watch时需要build压缩版代码,可自行修改)。npm run watch-dev # 启动watch模式,本地开发环境(通常用不上)npm run watch-test # 启动watch模式,测试环境npm run watch # 启动watch模式,生产环境Yarn和NPM的选择?通常使用NPM做包管理,但此项目使用Yarn,因为Yarn有:速度快、可离线安装、锁定版本、扁平化等更多优点。如果需要从npm切换到yarn,或者从yarn切换到npm时,请整体移除node_modules目录,及yarn.lock/package-lock.json文件,因yarn和npm两者的策略不同,导致相同的package.json列表安装后的node_modules结构是不同的(虽然这并不会引发bug,但建议在切换时清除后重新install)。Yarn常用命令yarn / yarn install // 安装全部(package.json)依赖包 —— npm installyarn run [dev] // 启动scripts命令yarn add [pkgName] // 安装依赖包(默认安装到dependencies下) —— npm install [pkgName]yarn add [pkgName]@[version] // 安装依赖包,指定版本 —— npm install [pkgName]@[version]yarn add [pkgName] -D // 安装依赖包,指定到devDependencies —— npm install [pkgName] -Dyarn remove [pkgName] // 卸载依赖包 —— npm uninstall [pkgName]yarn upgrade [pkgName] // 升级依赖包 —— npm update [pkgName]yarn upgrade [pkgName]@[version] // 升级依赖包,指定版本参考文档yarn中文网yarn安装 (预警:如果本机已经安装过NodeJS,使用brew安装yarn时,推荐使用brew install yarn --without-node命令,否则可能导致其它bug。)yarn命令yarn和npm命令对比Babel 转码这是最新的 babel 配置,和网上的诸多教程可能有不同,可以自行测试验证有效性。基础依赖包 ...

June 1, 2019 · 12 min · jiezi

实现小型打包工具

思路图解 思路:A方法找出入口文件所有的依赖关系 读取并编译入口文件代码依据入口文件代码广度遍历所有依赖文件(包括子级)对外输出依赖关系通过构建CommonJS代码来获取exports导出的内容 构建modules对象字符串(key为文件id, 值为[对应的函数, mapping])构建result函数字符串,并传入modules参数,函数中构建require函数,用于获取并执行对应文件执行require(entry), 即执行对应的文件有哪些功能点 读取并编译文件代码获取所有依赖文件实现打包功能(构建出CommonJS的写法)缺点: 是用relativePath做文件模块的唯一标识,容易冲突B方法与A方法大体思路一致。 区别 createCode函数 -》createAsset函数。 createAsset函数在返回值对象时,多一个标识符id(自增数字)getDependencies -》 createGraph, 给每个文件item添加mapping对象用来保存自己所依赖的文件path:id对象,方便使用时找到idbundle函数。构建modules字符串时,是 id和[function, mapping]做key, value。构建result字符串时,require函数,接收的是filepath对应的id. 有localRequire函数综上所述: 主要区别是此方法使用自增的id作为文件模块的唯一标识(不会重复)而不是文件相对路径(容易重复),但是这也导致代码有更大复杂性,比如模块自身需记录mapping(来记住依赖文件相对路径和其id的对应关系)。用到localRequire方法来进行相对路径和id的转换。 A方法多了处理css文件的能力 代码:见github https://github.com/sunchengua... 参考资料https://juejin.im/book/5bdc71... https://zhuanlan.zhihu.com/p/... https://zhuanlan.zhihu.com/p/...

May 30, 2019 · 1 min · jiezi

webpack4322系列教程02-mode

简介 mode(模式)是webpack4.0.0新增的配置,用来指定webpack使用对应模式的内置优化;它有三个可选模式:production、development、none;默认为production。 选项描述development通过DefinePlugin插件将 process.env.NODE_ENV 的值设为 development。启用 NamedChunksPlugin 和 NamedModulesPlugin。production通过DefinePlugin插件将 process.env.NODE_ENV 的值设为 production。启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 TerserPlugin.none通过DefinePlugin插件将 process.env.NODE_ENV 的值设为 node。使用默认的优化项。演示下面通过一段代码分别演示一个每一个模式打包输出的文件内容:源码地址 第一步:编写入口文件和依赖代码 // webpack@4.32.2系列教程/demo02-mode/src/role.jsexport default class Role { constructor(name, skill) { this.name = name; this.skill = skill; }}// webpack@4.32.2系列教程/demo02-mode/src/index.jsimport Role from './role'const role = new Role('乔峰', '降龙十八掌');console.log(role);console.log('process.env.NODE_ENV: ', process.env.NODE_ENV);第二步:编写webpack配置 & 启动webpack // webpack@4.32.2系列教程/demo02-mode/scripts/build.jsconst webpack = require('webpack');// 创建编译器对象const compiler = webpack({ // mode模式:webpack4.0.0新增配置,用来指定webpack使用相应模式的内置优化。 // mode: 'development' // 会将 process.env.NODE_ENV 的值设为 development。启用 NamedChunksPlugin 和 NamedModulesPlugin。 // mode: 'production' // 会将 process.env.NODE_ENV 的值设为 production。启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 UglifyJsPlugin. mode: 'none' // 使用默认优化项});// 启动webpackcompiler.run((err, stats) => { if (err) { console.error(err); return; } // 输出编译成功信息 console.log(stats.toString({ colors: true }));});第三步:cd到demo02-mode文件夹下,运行node scripts/build.js ...

May 30, 2019 · 1 min · jiezi

面试必备webpack-中那些最易混淆的-5-个知识点

面试必备!webpack 中那些易混淆的 5 个知识点前两天为了优化公司的代码打包项目,恶补了很多 webpack4 的知识。要是放在几年前让我学习 webpack 我肯定是拒绝的,之前看过 webpack 的旧文档,比我们内部项目的文档还要简陋。 但是最近看了一下 webpack4 的文档,发现 webpack官网的 指南 写的还不错,跟着这份指南学会 webpack4 基础配置完全不是问题,想系统学习 webpack 的朋友可以看一下。 今天我主要分享的是一些 webpack 中的易混淆知识点,也是面试的常见内容。我把这些分散在文档和教程里的内容总结起来,目前看是全网独一份,大家可以加个收藏,方便以后检索和学习。 <br/> 友情提示:本文章不是入门教程,不会费大量笔墨去描写 webpack 的基础配置,请读者配合教程源代码食用。<br/> 1.webpack 中,module,chunk 和 bundle 的区别是什么?说实话我刚开始看 webpack 文档的时候,对这 3 个名词云里雾里的,感觉他们都在说打包文件,但是一会儿 chunk 一会儿 bundle 的,逐渐就迷失在细节里了,所以我们要跳出来,从宏观的角度来看这几个名词。 webpack 官网对 chunk 和 bundle 做出了解释,说实话太抽象了,我这里举个例子,给大家形象化的解释一下。 首先我们在 src 目录下写我们的业务代码,引入 index.js、utils.js、common.js 和 index.css 这 4 个文件,目录结构如下: src/├── index.css├── index.html # 这个是 HTML 模板代码├── index.js├── common.js└── utils.jsindex.css 写一点儿简单的样式: ...

May 29, 2019 · 5 min · jiezi

Webpack-学习思路

转自 极客时间的《玩转webpack》

May 29, 2019 · 1 min · jiezi

creatreactapp3-配置文件分析2

文件结构分析 env.js // Load environment variables from .env* files. Suppress warnings using silent// if this file is missing. dotenv will never modify any environment variables// that have already been set. Variable expansion is supported in .env files.// https://github.com/motdotla/dotenv// https://github.com/motdotla/dotenv-expand//注释其实写的很清楚,用dotenv和dotenv-expand工具读取所有.env*文件,获取变量dotenvFiles.forEach(dotenvFile => { if (fs.existsSync(dotenvFile)) { require('dotenv-expand')( require('dotenv').config({ path: dotenvFile, }) ); }});//最后赋值给process.env对象// Stringify all values so we can feed into Webpack DefinePlugin const stringified = { 'process.env': Object.keys(raw).reduce((env, key) => { env[key] = JSON.stringify(raw[key]); return env; }, {}), };modules.js其实就两个函数,为了读取jsconfig.json或者tsconfig.json文件中的配置,两个文件不能同时存在. ...

May 29, 2019 · 3 min · jiezi

creatreactapp3-配置文件分析1eject之后

菜鸟学习react中,配置文件有点乱,研究一波。 yarn eject之后,文件目录相比之前只是多了config和scripts两个文件夹,package.json多了很多配置项,所以本文主要解决config和package.json两个部分. 一.config文件夹下,还有一个jest文件夹是jest测试文件,cssTransform.js和fileTransform.js对应package.json中的 "transform": { "^.+\\.(js|jsx|ts|tsx)$": "<rootDir>/node_modules/babel-jest", "^.+\\.css$": "<rootDir>/config/jest/cssTransform.js", "^(?!.*\\.(js|jsx|ts|tsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js" },二.重点分析,从package.json命令行入手, "scripts": { "start": "node scripts/start.js", "build": "node scripts/build.js", "test": "node scripts/test.js" },看命令就知道scripts下的三个文件,分别对应开发,打包和测试三个环境的入口。 config/path.js里面路径变量 const resolveApp = relativePath => path.resolve(appDirectory, relativePath);//解析对应文件的绝对路径const getPublicUrl = appPackageJson => envPublicUrl || require(appPackageJson).homepage;//赋值下面变量publicUrl,从env.js或者package.json中获取homepagefunction getServedPath(appPackageJson) { const publicUrl = getPublicUrl(appPackageJson); const servedUrl = envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : '/'); return ensureSlash(servedUrl, true);}//服务域名 ---------- dotenv: resolveApp('.env'), appPath: resolveApp('.'), appBuild: resolveApp('build'), appPublic: resolveApp('public'), appHtml: resolveApp('public/index.html'), appIndexJs: resolveModule(resolveApp, 'src/index'), appPackageJson: resolveApp('package.json'), appSrc: resolveApp('src'), appTsConfig: resolveApp('tsconfig.json'), appJsConfig: resolveApp('jsconfig.json'), yarnLockFile: resolveApp('yarn.lock'), testsSetup: resolveModule(resolveApp, 'src/setupTests'), proxySetup: resolveApp('src/setupProxy.js'), appNodeModules: resolveApp('node_modules'), publicUrl: getPublicUrl(resolveApp('package.json')), servedPath: getServedPath(resolveApp('package.json')),1.start.js 其实就是开发环境devserver的配置和启动 ...

May 28, 2019 · 3 min · jiezi

vuecli3中vueconfigjs配置

在使用vue-cli3创建项目后,因为webpack的配置均被隐藏了,当你需要覆盖原有的配置时,则需要在项目的根目录下,新建vue.config.js文件,来配置新的配置。配置的相关字段vue.config.js会被自动加载module.exports = { /* 部署生产环境和开发环境下的URL:可对当前环境进行区分,baseUrl 从 Vue CLI 3.3 起已弃用,要使用publicPath */ /* baseUrl: process.env.NODE_ENV === 'production' ? './' : '/' */ publicPath: process.env.NODE_ENV === 'production' ? '/public/' : './', /* 输出文件目录:在npm run build时,生成文件的目录名称 */ outputDir: 'dist', /* 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录 */ assetsDir: "assets", /* 是否在构建生产包时生成 sourceMap 文件,false将提高构建速度 */ productionSourceMap: false, /* 默认情况下,生成的静态资源在它们的文件名中包含了 hash 以便更好的控制缓存,你可以通过将这个选项设为 false 来关闭文件名哈希。(false的时候就是让原来的文件名不改变) */ filenameHashing: false, /* 代码保存时进行eslint检测 */ lintOnSave: true, /* webpack-dev-server 相关配置 */ devServer: { /* 自动打开浏览器 */ open: true, /* 设置为0.0.0.0则所有的地址均能访问 */ host: '0.0.0.0', port: 8066, https: false, hotOnly: false, /* 使用代理 */ proxy: { '/api': { /* 目标代理服务器地址 */ target: 'http://47.100.47.3/', /* 允许跨域 */ changeOrigin: true, }, }, },}正在努力学习中,若对你的学习有帮助,留下你的印记呗(点个赞咯^_^)往期好文推荐: ...

May 28, 2019 · 1 min · jiezi

webpack40从零开始单页多页应用配置三-辅助工具

webpack4.0从零开始单页(多页)应用配置 (一)webpack4.0从零开始单页(多页)应用配置(二) css相关项目引入Less安装Less, less-loader npm install --save-dev less less-loader修改webpack.config.js loader配置 { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }, { test: /\.less$/, exclude: /node_modules/, use: [ 'style-loader', 'css-loader', 'less-loader', ] },css自动添加前缀一些css3样式需要添加各个厂家的前缀才能生效,而现在css3运用比较长见,显然我们没必要在每个地方去添加前缀。 安装:postcss-loader 与autoprefixer插件。 npm i --save-dev postcss-loader autoprefixer根目录下新增postcss.config.js文件,并添加以下代码: module.exports = { plugins: [ require('autoprefixer') ]}修改webpack配置如下: { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }, { test: /\.less$/, exclude: /node_modules/, use: [ 'style-loader', 'css-loader', 'postcss-loader', 'less-loader', ] },postcss-loader还可以支持许多插件,详情请查看https://github.com/postcss/po... ...

May 28, 2019 · 2 min · jiezi

Webpack-HMR-原理解析

Hot Module Replacement(简称 HMR)包含以下内容: 热更新图热更新步骤讲解 第一步:webpack 对文件系统进行 watch 打包到内存中webpack-dev-middleware 调用 webpack 的 api 对文件系统 watch,当文件发生改变后,webpack 重新对文件进行编译打包,然后保存到内存中。 webpack 将 bundle.js 文件打包到了内存中,不生成文件的原因就在于访问内存中的代码比访问文件系统中的文件更快,而且也减少了代码写入文件的开销。 这一切都归功于memory-fs,memory-fs 是 webpack-dev-middleware 的一个依赖库,webpack-dev-middleware 将 webpack 原本的 outputFileSystem 替换成了MemoryFileSystem 实例,这样代码就将输出到内存中。 webpack-dev-middleware 中该部分源码如下: // compiler // webpack-dev-middleware/lib/Shared.js var isMemoryFs = !compiler.compilers && compiler.outputFileSystem instanceof MemoryFileSystem; if(isMemoryFs) { fs = compiler.outputFileSystem; } else { fs = compiler.outputFileSystem = new MemoryFileSystem(); }第二步:devServer 通知浏览器端文件发生改变在启动 devServer 的时候,sockjs) 在服务端和浏览器端建立了一个 webSocket 长连接,以便将 webpack 编译和打包的各个阶段状态告知浏览器,最关键的步骤还是 webpack-dev-server 调用 webpack api 监听 compile的 done 事件,当compile 完成后,webpack-dev-server通过 _sendStatus 方法将编译打包后的新模块 hash 值发送到浏览器端。 ...

May 27, 2019 · 3 min · jiezi

还学不会webpack看这篇

Webpack已经流行好久了,但很多同学使用webpack时还是一头雾水,一下看到那么多文档、各种配置、各种loader、plugin立马就晕头转向了。我也不例外,以至于很长一段时间对webpack都是一知半解的状态。但是想要继续做好前端,webpack是必须得跨过的一道坎,其实掌握webpack并不难,只是我们没有找到正确的方法。本文就是我自己在学习webpack时的一点心得体会,供大家参考。 什么是webpack?一句话概括:webpack是一个模块打包工具(module bundler)。重点在于两个关键词“模块”和“打包”。什么是模块呢?我们回顾一下曾经的前端开发方式,js文件通过script标签静态引入,js文件之间由于没有强依赖关系,如果文件1要用到文件2的某些方法或变量,则必须将文件1放到文件2后面加载。随着项目的增大,js文件之间的依赖关系越发错综复杂,维护难度也越来越高。这样的困境驱使着前端工程师们不断探索新的开发模式,从后端、app的开发模式中我们获得灵感,为什么不能引入“模块”的概念让js文件之间可以相互引用呢?模块1要使用模块2的功能,只需要在该模块1中明确引用模块2就行了,而不用担心它们的排列顺序。基于这种理念,CommonJS和 AMD规范被创造了出来,然后有了require.js、system.js这样的前端模块加载工具和node的模块系统,直到现在流行的es6 module。 模块的引入解决了文件之间依赖引用的问题,而打包则解决了文件过多的问题。当项目规模增大,模块的数量数以千计,浏览器如果要加载如此多的文件,页面加载的速度势必会受影响,而bundler可以把多个关联的文件打包到一起从而大量减少文件的数量提高网页加载性能。提供模块化的开发方式和编译打包功能就是webpack的核心,其他很多功能都围绕它们展开。 核心概念Module(模块)对于webpack,模块不仅仅是javascript模块,它包括了任何类型的源文件,不管是图片、字体、json文件都是一个个模块。Webpack支持以下的方式引用模块: ES2015 import 方法CommonJs require() 方法AMD define 和 require 语法css/sass/less文件中的 @import 语法url(...) 和 <img src=...> 中的图片路径Dependency Graph(依赖关系图)所谓的依赖关系图是webpack根据每个模块之间的依赖关系递归生成的一张内部逻辑图,有了这张依赖关系图,webpack就能按图索骥把所有需要模块打包成一个bundle文件了。 Entry(入口)绘制依赖关系图的起始文件被称为entry。默认的entry为 ./src/index.js,或者我们可以在配置文件中配置。entry可以为一个也可以为多个。 单个entry:module.exports = { entry: './src/index.js'}或者 module.exports = { entry: { main: './src/index.js' }};多个entry,一个chunk我们也可以指定多个独立的文件为entry,但将它们打包到一个chunk中,此种方法被称为 multi-main entry,我们需要传入文件路径的数组: module.exports = { entry: ['./src/index.js', './src/index2.js', './src/index3.js']}但是改种方法的灵活性和扩展性有限,因此并不推荐使用。 多个entry,多个chunk如果有多个entry,并且每个entry生成对应的chunk,我们需要传入object: module.exports = { entry: { app: './src/app.js', admin: './src/admin.js' }};这种写法有最好的灵活性和扩展性,支持和其他的局部配置(partial configuration)进行合并。比如将开发环境和生产的配置分离,并抽离出公共的配置,在不同的环境下运行时再将环境配置和公共配置进行合并。 Output(出口)有了入口,对应的就有出口。顾名思义,出口就是webpack打包完成的输出,output定义了输出的路径和文件名称。Webpack的默认的输出路径为 ./dist/main.js。同样,我们可以在配置文件中配置output: module.exports = { entry: './src/index.js', output: { path: __dirname + '/dist', filename: 'bundle.js' }};多个entry的情况当有多个entry的时候,一个entry应该对应一个output,此时输出的文件名需要使用替换符(substitutions)声明以确保文件名的唯一性,例如使用入口模块的名称: ...

May 27, 2019 · 2 min · jiezi

自己写一个自动发布到sftp服务器的webpack插件

起因:公司的前端项目一直是手动部署到sftp,很容易出错,最近没事想把手动做成自动部署,说干就干。最开始当然是去npm和gayhub查找各种类似的部署工具,用了开源的,有各种各样的问题: 1. 不能删除旧代码(最大的问题)2. 上传到服务器之后不会自动退出命令行3. 更小问题就不说了,强迫症的我受不了,必须自己弄一个gayhub地址 使用方法很简单,安装:npm install webpack-deploy-sftp -save-dev在webpack.config.js中加入 const WebpackDeploySftp = require('webpack-deploy-sftp')plugins: [ new WebpackDeploySftp({ port: 'port', host: 'host', user: 'user', password: 'password', path: 'localPath', remotePath: 'remotePath' })]

May 27, 2019 · 1 min · jiezi

webpack40从零开始单页多页应用配置二

webpack4.0从零开始单页(多页)应用配置 (一) 加载图片通过webpack运行起的项目如果不对图片资源做处理是不会加载到文件的。例:我们在src目录下添加一个image目录并且放入一张图片在里面:且在style.css文件加入如下代码: html, body{ height: 100%; background-color: red; background-image: url('./image/yangmi.jpg')}执行npm run dev发现并不会如期那样,界面上呈现图片。且报如下错误提示已经很智能了,需要安装loader解析此类文件。 安装:npm install --save-dev file-loader url-loader 之前讲过处理资源一般是在moude配置,所以在moude下的规则配置如果就能加上图片了{ test: /\.jpg|\.png|\.gif|\.jpeg|\.svg/, use: { loader: 'url-loader', options: { limit: 8192 //将小于8kb的图片 转为base64, 这样就会减少发送http的请求提高性能 } }}再次执行,npm run dev; 加载字体项目中可能会加入各种字体库,现在除了svg,我们用得比较多的就是iconfont了所以这里我们拿iconfont举例:我们在iconfont图标库里导出图标,并将放在src目录下命名为font: webpack.config.js添加配置如下: { test: /\.(woff|woff2|eot|ttf|otf)$/, use: { loader:'url-loader' }}并在main.js文件引入iconfont.css并添加一个名为iconauth的名字并执行npm run dev 如下: 引用vue安装: npm install vue --save npm install --save-dev vue-loader webpack.config.js { test: /\.vue$/, use: { loader: 'vue-loader' }}main.js ...

May 27, 2019 · 2 min · jiezi

高性能方案实现antdesign在运行时动态改变主题色利用webpackthemecolorreplacer

今天利用webpack-theme-color-replacer插件,为ant-design实现了在运行时动态切换主题色的功能,无需在页面进行less的编译,提升了切换速度。有需要的同学可以参考下。 源码:https://github.com/hzsrc/ant-... 效果预览:https://deploy-preview-4289--...在右侧中央的配置按钮点开可以切换主题色。 实现方案:方案是统一的,见之前的文章:https://segmentfault.com/a/11... 基本步骤:基于 ant-design-pro 这个项目上进行修改: 1、webpack加入插件配置:查看修改:https://github.com/hzsrc/ant-... 2、运行时动态切换主题色,查看修改:https://github.com/hzsrc/ant-... (因笔者时间有限,color.less文件中的colorPalette变换函数所涉及的颜色值没有纳入) 实现效果:初始主题色: 切换后主题色:

May 25, 2019 · 1 min · jiezi

Script-error-问题解法

问题当第三方脚本报错时因为跨域问题不会暴露详细的错误信息,取而代之的是统一的 Script error 我们遇到的情况是页面和js的二级域名一样,并且设置了document.domain,chrome浏览器能够展示详细错误栈;但是很多手机浏览器依然是Script error。 解法我们使用的cdn是阿里云,实际上他已经给出了此问题的解法 阅读之后我们知道只要给script标签添加crossorigin属性就可以了,之后效果如图 具体方法我们项目使用的是webpack,对html进行修饰的插件大家用的应该都是html-webpack-plugin,此插件的衍生插件script-ext-html-webpack-plugin能够满足我们的需求。 plugins: [ .... new HtmlWebpackPlugin({ inject: true, template: paths.appHtmlProd, }), new ScriptExtHtmlWebpackPlugin({ custom: { test: /\.js$/, attribute: 'crossorigin', value: 'anonymous' } }), ...]

May 24, 2019 · 1 min · jiezi

基于React和Webpack的Optimize

公司项目采用使用React16+Webpack3+Graphql来作为技术构建,在图像等方面上使用七牛;下面是本人将会围绕当前技术来进行优化的体验,理解和使用到的都不算特别复杂,但是点比较多,可能可以启发一下; React版本升级(当前是16.8.6) 如果是React15的更应该升级到16,除新的Api外,React本身也进行了优化如Fiber等,体积也更小; Api更新 1、 React.Memo:LessState组件上采用React.Memo来进行处理,代替原先的PureComponent; 2、 去除依赖库:如果原先有使用一些Lazy库,可以考虑直接使用React.Lazy来实现,减少打包体积,原先的路由懒加载是直接写了一个方法,也可以使用React.Lazy来完成并且Suspense可以实现占位图; import React, { Component } from 'react' import LoadingViewContainer from '../components/LoadingViewContainer' export default function asyncComponent(importComponent) { return class extends Component { state = { component: null } async componentDidMount() { const { default: component } = await importComponent() this.setState({ component: component }) } render() { const C = this.state.component return C ? <C {...this.props} /> : <LoadingViewContainer /> } } }3、 使用Hooks:Hooks是React16.8之后出的一个新的Api,与以前的Class Component改变很多,如useReducer有人用来实现Redux,至于是否可以真的代替,这个还没有深入了解,按官方说法,因为不使用原先生命周期以及逻辑业务的复用性,可以减少很多代码;具体的不在这里去详写,本身也理解不够透彻,只贴一个自己写的简单的代替原先React-Helmet(Helmet),后续可能会单独写一下Hooks; ...

May 24, 2019 · 1 min · jiezi

webpack429x成神之路二十四-手动配置vuecli集成typescript

目录 上节: 手动配置vue-cli下 上节目录: 本节给之前配的vue-cli集成ts,让它支持ts + vue的开发。首先修改build/webpack.base.js: const HTMLPlugin = require('html-webpack-plugin');const VueLoaderPlugin = require('vue-loader/lib/plugin');const {resolve} = require('path');module.exports = { entry: resolve(__dirname, '../src/main.ts'), resolve: { // 这里可以配置些文件后缀,用于写路径时可省略后缀(会影响打包速度,不建议配太多) extensions: [ '.tsx', '.ts', '.js', 'vue', 'less' ] }, module: { rules: [{ // 识别.vue文件 test: /\.vue$/, loader: 'vue-loader' }, { // 识别.ts或.tsx文件 test: /\.tsx?$/, use: 'ts-loader' }, { // 用于识别vue文件中的script块 test: /\.js$/, loader: 'babel-loader', }, { test: /\.(gif|jpg|jpeg|png|svg|ttf|woff)$/, loader: 'url-loader' }] }, plugins: [ new HTMLPlugin({ template: resolve(__dirname, '../index.html') }), // 将定义过的其它规则复制并应用到 .vue 文件里相应语言的块 new VueLoaderPlugin() ]};在rule里加了ts规则后,通过VueLoaderPlugin也能将其用于.vue文件 ...

May 23, 2019 · 2 min · jiezi

从0开始自己实行webpack打包不会打我手动滑稽

webpackwebpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。接下来我们从0开始,一步一步实现我们的打包,作为入门,希望大家有所收获。 源码地址,欢饮Star[https://github.com/WangDeTao/...] 整体项目模块介绍- 00simple(只包含简单的js文件打包)- 01simple-dev-server(本地的服务,包含js,css,图片,html,增加loader,plugin,derServer)- 02simple-production(打包成生产环境静态资源)- css(css文件)- imgs(图片文件)- js(js文件one.js/two.js)- static(viewport.js,在index.html引入)00simple介绍首先用npm init 来初始化管理我们的项目,接着安装webpack和webpack-cli; npm init -ynpm install -D webpack webpack-cli安装完成以后,创建webpack.config.js文件,配置好入口和出口; <font color=red>注意:</font> 出口需要指定文件名和路径,其中__dirname 表示当前文件所在目录的完整目录名 const path = require('path')module.exports = { entry:'./index.js', output:{ filename:'bundle.js', path:path.resolve(__dirname,'./bundle') }}执行打包命令npx webpack就可以看到如下图生成了bundle文件夹,执行node bundle/bundle.js 会看到输出了index.js里面到处的对象 <font color=red>注意:</font> npx 会帮你执行依赖包里的二进制文件。 但是更多的时候我们是希望通过'npm run xxx'的形式来打包,这个时候也很简单,只需要在package.json的script下面添加 "scripts": { "00simple": "webpack --config webpack.config.js" }接着在terminal输入'npm run 00simple'即可,run是run-script的简写。 01simple-dev-server介绍这一章节我们将会增加loader,plugin和devServer的内容。 loader和plugin的区别loader 用于对模块的源代码进行转换,比如es6/7转es3,less/sass转css等plugin 用于扩展webpack的功能,比如压缩混淆,整合html和js,复制文件等本章节的loader和pluginstyle-loader/css-loader 处理cssfile-loader 处理图片html-webpack-plugin 整合html和打包的js文件首先安装上述提到的loader npm install -D style-loader css-loader file-loader同时在webpack.config.js增加module 并且 在index.js引入css和图片,并将图片添加到html中。 ...

May 22, 2019 · 2 min · jiezi

vue项目添加多页面配置

公司使用vue-cli创建的vue项目在初始化时并没有做多页面配置,随着需求的不断增加,发现有必要使用多页面配置。看了很多vue多页面配置的文章,基本都是在初始化时就配置了多页面。而且如果使用这些实现,需要调整当前项目的目录结构,这点也是不能接受的。 最后,参考这些文章,在不调整当前项目目录结构实现了多页面的配置的添加。这里做下记录、总结,方便以后复用。如果还能有幸帮助到有同样需求的童鞋的话,那就更好了。 实现步骤添加新增入口相关文件;使用变量维护多入口;开发环境读取多入口配置;生产环境读取多入口配置;新增入口相关文件在src目录下新增一个page1文件夹,新建新页面的所需的相关文件(入口文件、HTML模板文件等)。我这边直接vue-cli初始化创建相关文件复制了一份到page1文件夹下。如下: ├─App.vue├─main.js├─page1.html // 这里模板文件名称需要与文件夹名称相同,方便输出模板读取├─router| └index.js├─components| └HelloWorld.vue├─assets| └logo.pngpage1/router/index.js需要对该页面的所有路由添加同文件夹名的公共路径,用于解析: import Vue from 'vue'import Router from 'vue-router'import HelloWorld from '@/page1/components/HelloWorld' // 这里也需要留意Vue.use(Router)export default new Router({ mode: 'history', base: '/', routes: [ { path: '/page1/', redirect: '/page1/index' }, { path: '/page1/index', name: 'HelloWorld', component: HelloWorld } ]})使用变量维护多入口我们在项目目录下的build/utils.js的最后exports一个指定多入口的对象。如下: // 这里,每个属性就是一个页面配置,指定该页面的入口文件// 如果需要添加,只需多增加一个属性// 属性名必和html模板文件名、目录名称相同exports.multipleEntrys = { page1: './src/page1/main.js'}之所以使用build/utils.js,是因为该文件在webpack.base.conf.js、webpack.prod.conf.js、webpack.dev.conf.js都用导入。 开发环境读取多入口配置首先,在build/webpack.base.conf.js中,我们把上面定义的入口添加进entry配置: entry: { app: './src/main.js', ...utils.multipleEntrys // entry添加该行 }然后,在build/webpack.dev.conf.js添加路径解析和多页面输出: // 添加解析,将historyApiFallback的属性修改如下: historyApiFallback: { rewrites: [ // 将所有多入口遍历成路径解析项 ...((()=>{ let writes = [] for(let prop in utils.multipleEntrys){ // 使用属性名匹配为正则 // 这就是上面“需要对该页面的所有路由添加同文件夹名的公共路径”的原因 let reg = new RegExp(`^/${prop}/`) writes.push({ from: reg, // 使用属性名读取模板文件 // 这就是上面“模板文件名称需要与文件夹名称相同”的原因 to: path.posix.join(config.dev.assetsPublicPath, `${prop}.html`) }) } return writes })()), // 匹配所有路径一定要在最后,否则该匹配之后的项,不会被执行 { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') } ], }// 在已经的HtmlWebpackPlugin中添加chunks配置,否则默认页面会注入所有页面的js文件...plugins: [ ... new HtmlWebpackPlugin({ filename: 'index.html', template: 'index.html', inject: true, // 增加此行, // 'app'为默认入口名称,如果你的默认入口不是'app' // 则这里需要替换 chunks: ['manifest', 'vendor', 'app'] }) ...]...// 在`devWebpackConfig`定义之后,紧接着添加多页面输出:for(let prop in utils.multipleEntrys){ devWebpackConfig.plugins.push(new HtmlWebpackPlugin({ filename: `${prop}.html`, // html模板路径,使用属性名作为文件夹名称 // 这是新页面文件夹名称需要和多入口配置变量属性名相同的原因 template: `./src/${prop}/${prop}.html`, inject: true, chunks: ['manifest', 'vendor', prop], }))}最后,添加多页面相互跳转链接: ...

May 22, 2019 · 2 min · jiezi

webpack429x成神之路二十三-手动配置vuecli下

目录 上节: 手动配置vue-cli上 上节目录: 生成环境配置需求 每次内容变化,输出的文件名hash也会变化每次打包清理dist目录代码分割(分割第三方库)css分割以下都是修改build/webpack.prod.js 配置输出文件名// 省略output: { filename: 'js/[name].[contenthash:10].js' },// 省略清理输出目录(dist)安装插件:npm i clean-webpack-plugin -D // 省略const CleanWebpackPlugin = require('clean-webpack-plugin');output: { filename: 'js/[name].[contenthash:10].js' },plugins: [ new HTMLPlugin({ template: './index.html' }), // 将定义过的其它规则复制并应用到 .vue 文件里相应语言的块 new VueLoaderPlugin(), new CleanWebpackPlugin() ]// 省略代码分割配置optimization属性: // 省略 optimization: { // 配置代码分割 splitChunks: { // 要分割哪些模块:all(推荐), async(默认,只分隔异步代码), and initial chunks: 'all' } }// 省略css分割安装插件:npm i mini-css-extract-plugin -D // 省略const MiniCssExtractPlugin = require('mini-css-extract-plugin');module: { rules: [{ // 识别.vue文件 test: /\.vue$/, loader: 'vue-loader', }, { // 用于识别vue文件中的script块 test: /\.js$/, loader: 'babel-loader', }, { // 用于识别vue文件中的style块 test: /\.(css|less)$/, /* MiniCssExtractPlugin.loader代替vue-style-loader */ use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader'] }, { test: /\.(gif|jpg|jpeg|png|svg|ttf|woff)$/, loader: 'url-loader' }] },plugins: [ new HTMLPlugin({ template: './index.html' }), // 将定义过的其它规则复制并应用到 .vue 文件里相应语言的块 new VueLoaderPlugin(), new CleanWebpackPlugin(), // ... 忽略 vue-loader 插件 new MiniCssExtractPlugin({ filename: '[name].[contenthash:10].css' }) ],// 省略现在build/webpack.prod.js全部内容应该如下:注意修改mode选项 ...

May 21, 2019 · 3 min · jiezi

webpack429x成神之路二十二-手动配置vuecli上

目录 上节: 编写一个plugin 本节开始用之前介绍的知识来搭建个vue开发环境,其实如果把基础篇的那些内容掌握,配合文档,完全可以自己搭建出来。 开始新建一个空文件夹,并在文件夹下新建如下基本文件: .gitignore: node_modulesdist.idea.vscodeindex.html: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Webpack</title></head><body><div id="root"></div></body></html>package.json: { "name": "webpack-train", "version": "1.0.0", "description": "webpack4", "main": "index.js", "scripts": { "dev": "webpack-dev-server" }, "keywords": ["webpack4"], "author": "Madao", "license": "ISC"}然后新建src目录,并在src下新建main.js(入口)和App.vue(根组件): src/main.js: import Vue from 'vue';import App from './App.vue';new Vue({ el: '#root', render: h => h(App)});src/App.vue: <template> <div> <h1>hello {{msg}}</h1> </div></template><script> export default { name: 'App', data() { return { msg: 'webpack' } } }</script>在根目录下新建webpack.config.js: ...

May 21, 2019 · 2 min · jiezi

探索webpack运行时

前言本篇文章建议亲自动手尝试. 最近研究了 webpack 运行时源码, 在这篇文章中记录了我的探索 webpack 这个复杂的玩具方式, 并且以图形的形式将 webpack 运行时的流程给记录的下来. 我们讨论的是什么这篇文章主要记录的是 webpack 在将文件打包后是如何在浏览器中加载以及解析的流程. 手段webpack 实在是太复杂的了, 为了避免额外的干扰, 我使用最小化实例的方式来进行探究 webpack 是如何加载和解析模块文件的. 具体的手段:首先准备几个非常简单的 js 文件, 其次准备其对应的 webpack 配置文件, 逐一测试后观察其输出, 阅读其源码, 然后得出结论. 简单总结webpack 的运行时在解析同步模块的时候就和 nodejs 规则如出一辙. 什么意思, 每一个模块在运行前都会被一个函数进行包裹: (function (module, exports, __webpack_require__) { // do something})看起来和 nodejs 一样, 作用起来也一致, 这里的当前模块的导出模块和导入模块就是: exports_webpack_require_而当一个模块被需要的时候, webpack 就会执行这个函数获取其对应的 exports对象. 注意:我们需要的是模块执行完成后的 exports 对象而不是这个模块函数. 在 webpack 中我们可以使用 ESM 规范和 commonjs 规范来加载模块, 无论使用哪种规范, 实际上都可以被这种方式来包裹起来, 因为这两种常见的方式中都存在着相同的导入导出的概念, 所以 webpack 将这两种形式进行了统一包装消除了差异. ...

May 21, 2019 · 3 min · jiezi

webpack踩坑记录

webpack入门级配置(最新)目前最的正式版本是:4.31.0,推荐使用本地安装,webpack官网-指南1.初始化确认node 的版本号 node -v新建一个项目文件夹 mkdir demo初始化 npm init -y npm 安装 webpack webpack-cli --save-dev在项目文件夹下新建一个src文件夹,src文件夹包含index.js,index.html新建webpack配置文件 webpack.config.jsconst path = require('path');module.exports = { entry:'./src/index.js'. ouyput:{ path: path.resolve(__dirname,'dist'), filename: 'bundle.js', }}安装 webpack-dev-server本地安装webpack-dev-server npm i webpack-dev-server -D找到package.json文件,搜索scripts,添加 "dev": "webpack-dev-server --open --port 3000 --contentBase src --hot"代码此时在命令行运行npm run dev,即可打包文件安装html-webpack-plugin命令行运行npm install --save-dev html-webpack-plugin在webpack配置文件添加配置信息const HtmlWebpackPlugin = require('html-webpack-plugin');plugins:[new HtmlWebpackPlugin({template:'./dist/index.html'})]加载css命令行运行npm install --save-dev style-loader css-loader配置文件配置module:{reules:[{test:/\.css$/,use:['style-loader','css-loader']}]}安装babel-loader命令行运行npm install -D babel-loader @babel/core @babel/preset-env webpack配置文件配置module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } ]}运行npm install -D @babel/plugin-transform-runtime配置文件use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'], plugins: ['@babel/plugin-transform-runtime'] } }使用vue命令行运行 npm i vue -D配置文件配置# const VueLoaderPlugin = require('vue-loader/lib/plugin');# resolve:{ alias:{ 'vue$':"vue/dist/vue.esm.js" } } 安装vue-loader命令行npm install -D vue-loader vue-template-compiler配置文件+ const VueLoaderPlugin = require('vue-loader/lib/plugin');- rules: [ // ... 其它规则 { test: /\.vue$/, loader: 'vue-loader' } ] - plugins: [ // 引入这个插件! new VueLoaderPlugin() ]附上源代码 ...

May 19, 2019 · 2 min · jiezi

webpack429x成神之路二十-编写一个loader

目录 上节: css代码分割 目录: 先改一下src/index.js: import _ from 'lodash';const root = document.getElementById('root');root.innerText = _.join(['hello', 'webpack'], '-');现在写一个简单的loader,将所有的webpack替换成其它内容,内容可通过options配置。在根目录新建loaders/replace-loader.js。 loaders/replace-loader.js: const { getOptions } = require('loader-utils');module.exports = function(source) { /* this指向webpack source:打包后的文件内容 this.query options参数 */ const options = getOptions(this) || {}; // 返回处理后的结果,相当于是打包拦截器 return source.replace('webpack', options.name || 'Madao');}source是打包后生成的文件,options可以拿到配置参数,这个loader会将所有webpack替换成options.name的内容,如果没指定options.name, 就替换成Madao. 然后引用这个loader, 修改webpack/webpack.base.js: const HtmlWebpackPlugin = require('html-webpack-plugin');const { resolve } = require('path');module.exports = { entry: './src/index.js', output: { path: resolve(__dirname, '../bundles') }, // 注册loader resolveLoader: { // loader查找顺序,从左到右 modules: ['node_modules', './loaders/'] }, module: { rules: [{ test: /\.js$/, exclude: /node_modules/, // 先不传options use: ['replace-loader', 'babel-loader'] }, { test: /\.(gif|jpg|jpeg|png|svg)$/, use: ['url-loader'] }] }, plugins: [ new HtmlWebpackPlugin({ template: './index.html' }) ]};安装loader工具库:npm i loader-utils -D然后npm run build, 打开bundles下的main.[contenthash].js文件,应该可以搜索到Madao: ...

May 18, 2019 · 2 min · jiezi

webpack429x成神之路十九-css代码分割

目录 上节: 懒加载 上节目录如下: css代码分割一般用于生产环境,先修改src/index.js: import './styles/index.less';import _ from 'lodash';const root = document.getElementById('root');root.innerText = _.join(['hello', 'webpack']);styles/index.less: #root{ color: blue;}然后npm run build,浏览器运行bundles/index.html: 现在样式是通过style标签内联在页面上的。 现在修改配置,让样式通过link标签外部引入:webpack/webpack.prod.js: const CleanWebpackPlugin = require('clean-webpack-plugin');const merge = require('webpack-merge');const baseConfig = require('./webpack.base');const MiniCssExtractPlugin = require('mini-css-extract-plugin');module.exports = merge(baseConfig, { mode: 'production', output: { filename: '[name].[contenthash:10].js' }, devtool: 'cheap-module-source-map', module: { rules: [{ test: /\.less$/, use: [{ loader: MiniCssExtractPlugin.loader, }, 'css-loader', 'postcss-loader', 'less-loader'] }] }, plugins: [ new MiniCssExtractPlugin({ filename: '[name].css', chunkFilename: '[id].css' }), new CleanWebpackPlugin() ], optimization: { splitChunks: { chunks: 'all' } }});安装mini-css-extract-plugin:npm i mini-css-extract-plugin -D ...

May 18, 2019 · 1 min · jiezi

webpack429x成神之路十八-懒加载

目录 上节: 代码分割(code spliting)下 上节目录如下: 其实在代码分割时已经用过懒加载了,src/index.js内容如下: function getComponent() { const element = document.createElement('div'); return import(/* webpackChunkName: "lodash" */ 'lodash').then(({ default: _ }) => { const element = document.createElement('div'); element.innerHTML = _.join(['Hello', 'webpack'], ' '); return element; }).catch(error => 'An error occurred while loading the component');}// 按需加载,当点击了页面,才会引入lodash,也是单页应用路由懒加载的实现原理window.addEventListener('click', function(){ getComponent().then(component => { document.body.appendChild(component); })});npm run build看生成的文件: 这三个文件将被用于浏览器,现在运行index.html打开f12: 如果不点击页面,就不会加载lodash文件,现在点击一下页面: 页面上出现hello webpack并且加载了lodash文件,这就是懒加载(按需加载 | 异步加载) 下节:css代码分隔(待更新)

May 18, 2019 · 1 min · jiezi

webpack40从零开始单页多页应用配置-一

理解webpack核心概念借用官网的话:“webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。” 如图加上概述,开发的各种js模块,以及图片 + sass代码等 通过webpack编译之后生成单个js文件css文件等 webpack4.0迁移如: module.loaders 改为 module.rulesjson-loader 不再需要手动添加 UglifyJsPlugin 压缩 loaders;使用new webpack.LoaderOptionsPlugin()代替 new webpack.LoaderOptionsPlugin({ minimize: true})ExtractTextWebpackPlugin 不再推荐使用,改为mini-css-extract-plugin以及常用的CommonsChunkPlugin被optimization.splitChunks代替了解更多可以查看webpack官网指南,里面有迁移介绍,以及各个部分都有讲哪些被弃用 webpack组成部分module.exports = { entry: {}, //入口起点,指示webpack应用使用哪个模块 支持String|Array|Object output: {}, //出口,告诉 webpack 在哪里输出它所创建的 bundles,以及命名文件default: './dist' module: {}, //loader插件,处理一些非javascript代码,转化为可用的代码 plugins: [], //webpack相关插件 resolve: {}, //用于帮助找到模块的绝对路径。一个模块可以作为另一个模块的依赖模块,然后被后者引用 devServer: {},//通过node起一个本地服务器,webpack-dev-server完成一些代理,mock数据热加载等功能 devtool: '',//此选项控制是否生成,以及如何生成 source map。主要用于开发和生产代码类型 mode: '', //模式 optimization: {}//优化生成的文件,如合并commonsChunks等 }webpack基础功能配置基础的已经弄懂之后,当然一行一行的配置才能有更加清晰的认知啦~创建package.json执行 npm init -y 或者 npm init -f 这两个会跳过提问阶段,直接生成新的package.json ...

May 18, 2019 · 2 min · jiezi

webpack429x成神之路十七-代码分割code-spliting下

目录 上节: 代码分割(code spliting)中 上节目录如下: 前两节代码分割只用到了splitChunks中的chunks属性,现在来看下其它属性 魔法注释先来打个包,npm run build: 可以看到lodash打包后的名字是vendors~lodash,这其实跟src/index.js中的一段注释有关: 现在删掉这段注释再打包: 就默认用[id]命名了,这就是魔法注释的作用,还有其它魔法注释如: / webpackPrefetch: true / 这段表示改模块开启Prefetch预加载<link rel="prefetch" href="verdor~main.js"> / webpackPreload: true / 这段表示改模块开启Preload预加载<link rel="preload" href="verdor~main.js"> 修改输出文件名虽然魔法注释能影响输出的文件名,但却不能完全控制,比如我就想让输出的文件名叫lodash呢?先恢复魔法注释,然后修改webpack/webpack.prod.js: // 省略optimization: { // 配置代码分割 splitChunks: { cacheGroups: { vendors: false, default: false } } }// 省略再打包: 这样就没有vendor~前缀了。 splitChunks其它属性先看下splitChunks的默认属性: module.exports = { //... optimization: { splitChunks: { chunks: 'async', minSize: 30000, maxSize: 0, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: '~', name: true, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true } } } }};属性很多,官网传送 ...

May 18, 2019 · 2 min · jiezi

webpack429x成神之路十六-代码分割code-spliting中

目录 上节: 代码分割(code spliting)上 上节目录如下: 分割异步代码之前src/index.js里都是同步代码: 现在来写段异步逻辑,修改src/index.js: function getComponent() { const element = document.createElement('div'); return import(/* webpackChunkName: "lodash" */ 'lodash').then(({ default: _ }) => { const element = document.createElement('div'); element.innerHTML = _.join(['Hello', 'webpack'], ' '); return element; }).catch(error => 'An error occurred while loading the component');}// 按需加载,当点击了页面,才会引入lodash,也是单页应用路由懒加载的实现原理window.addEventListener('click', function(){ getComponent().then(component => { document.body.appendChild(component); })});import()可以不加载文件并返回promise,参考:https://developer.mozilla.org... 现在来npm run build: 因为import()还只是个提案,我们得安装 @babel/plugin-syntax-dynamic-import插件才能用:npm i @babel/plugin-syntax-dynamic-import -D babel.config.js使用插件: module.exports = { presets: [ ["@babel/env", { // 设置打包后的代码将在哪些浏览器运行?只针它们做转化 targets: { edge: "17", firefox: "60", chrome: "67", safari: "11.1", }, // 目前@babel/polyfill依赖的core-js@2,需要指定此选项并安装 corejs: 2, /* * @babel/polyfill会将所有高阶语法转化,配置useBuiltIns只转化项目中用到的语法 *797k => 291k * 当useBuiltIns: "usage"时,入口文件就不需要import "@babel/polyfill"了 * 当useBuiltIns: "entry"时,需要在入口文件里import "@babel/polyfill" * */ useBuiltIns: "usage" } ] ], plugins: ["@babel/plugin-syntax-dynamic-import"]}再次npm run build,和之前一样会进行代码分割 ...

May 18, 2019 · 1 min · jiezi

webpack429x成神之路十五-代码分割code-spliting上

目录 上节: 区分开发和生产环境 上节目录如下: 什么是代码分割先来修改下src/index.js: import _ from 'lodash';_.join(['a', 'b', 'c', '-']);这里引入lodash并调用join方法,然后安装下lodash: npm i lodashnpm run build, 可以看到lodash和业务代码都打包在一起了,并且有70kb: 这里就会有个问题,项目中会引入很多第三方库,这些库根业务无关,内容几乎是不会改变的,如果都打包到一起,那么浏览器想要看到效果就必须执行完整个超大的main.js文件,如果能把不会变动的代码(不管是第三方还是自己写的),都单独打包到一个文件,且文件名每次都一样,那么浏览器以后刷新就能直接在缓存中读取,从而提升页面性能,这就是所谓的代码分割。 手动实现代码分割这里示范一下简单粗暴的做法,为了让大家更理解什么是代码分割新建src/js/lodash.jslodash.js代码如下: import _ from 'lodash';window._ = _;window上挂个属性'_',值为lodash,这样index.js就不用引入了:src/index.js: _.join(['a', 'b', 'c', '-']);然后把lodash.js设置为入口,webpack/webpack.base.js: // 省略entry: { main: './src/index.js', lodash: './src/js/lodash.js' },//省略执行npm run build: 可以看到lodash被单独打包成了一个文件,这就是代码分割 用webpack实现代码分割先恢复下代码,把src/js/lodash.js删了,src/index.js如下: import _ from 'lodash';_.join(['a', 'b', 'c', '-']);webpack/webpack.base.js删掉lodash入口: // 省略entry: './src/index.js',//省略这样代码就恢复了,代码分割的功能也没了。 然后在修改生产环境的配置,开启代码分割的选项webpack/webpack.prod.js: // 省略module.exports = merge(baseConfig, { mode: 'production', output: { filename: '[name].[contenthash:10].js' }, devtool: 'cheap-module-source-map', module: { rules: [{ test: /\.less$/, use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader'] }] }, plugins: [ new CleanWebpackPlugin() ], optimization: { // 配置代码分割 splitChunks: { // 要分割哪些模块:all(推荐), async(默认,只分隔异步代码), and initial chunks: 'all' } }});然后npm run build: ...

May 18, 2019 · 1 min · jiezi

webpack429x成神之路十四-区分开发和生产环境

目录 上节: 摇树优化(tree shaking) 上节目录如下: 环境介绍webpack的mode选项有三个值:development | production | none, 分别看下不同模式下webpack的默认配置: 详细参考:https://webpack.js.org/config... 从默认配置也可以看出,开发和生产模式下的配置很不一样,所以是有必要给开发和生产环境分别写一份配置。 开始现在webpack.config.js的内容大概是这样的: const { resolve } = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');const CleanWebpackPlugin = require('clean-webpack-plugin');module.exports = { mode: 'production', entry: './src/index.js', output: { filename: '[name].js', path: resolve(__dirname, 'bundles') }, // 开启devServer devServer: {}, // optimization: { // // production模式下默认开启 // usedExports: true // }, module: { rules: [{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' }, { test: /\.(gif|jpg|jpeg|png|svg)$/, use: ['url-loader'] }, { test: /\.less$/, use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader'] }] }, plugins: [ new HtmlWebpackPlugin({ template: './index.html' }), new CleanWebpackPlugin() ]};根目录下新建一个目录webpack, 并将webpack.config.js复制两份到该目录下,重命名为webpack.dev.js和webpack.prod.js,目录如下: ...

May 18, 2019 · 3 min · jiezi

webpack429x成神之路十三-摇树优化tree-shaking

目录 上节: source-map 上节目录如下: 概念官方:描述移除 JavaScript 上下文中的未引用代码。也就是希望webpack在打包时把没用到的函数删掉,最常见的就算第三方函数库:lodash,date-fns等。 新建src/js/math.js: export function add(...arg) { return arg.reduce((x, y) => x + y);}export function sub(...arg) { return arg.reduce((x, y) => x - y);}这里定义了两个函数,然后修改src/index.js: import {add} from './js/math';console.log(add(2, 4, 11));修改webpack.config.js的mode选项,将production改为development: // 省略mode: 'development',// 省略这样打包后就不会压缩代码了然后npm run build, 编辑器打开bundles/main.js,一直翻到最后: 可以看到,虽然index.js里只用到了add方法,但webpack还是会把math.js中导出的方法都进行打包,那么tree shaking就是用来解决这个问题的。 开启tree shaking在package.json里添加一个属性:package.json: // 省略"sideEffects": false,// 省略sideEffects如果设为false,webpack就会认为所有没用到的函数都是没副作用的,即删了也没关系。 修改wbpack.config.js: module.exports = { mode: 'development', entry: './src/index.js', output: { filename: '[name].js', path: resolve(__dirname, 'bundles') }, // 开启devServer devServer: {}, optimization: { // 优化导出的模块 usedExports: true }, module: { rules: [{ test: /\.(gif|jpg|jpeg|png|svg)$/, use: ['url-loader'] }, { test: /\.less$/, use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader'] }] }, plugins: [ new HtmlWebpackPlugin({ template: './index.html' }), new CleanWebpackPlugin() ]};然后npm run build, 打包bundles/main.js: ...

May 18, 2019 · 1 min · jiezi

webpack-代码分离快速指北

⭐️ 更多前端技术和知识点,搜索订阅号 JS 菌 订阅分离代码文件在此之前,首先要知道经常配置的 output 中有关 filename 和 chunkFilename 的区别;简单来说在 entry 定义的入口文件走的就是 filename 配置项,在入口文件内部引入的通常情况下是 chunk,走 chunkFilename 的配置 所以很多时候分离代码文件就是将不同的 chunk 分离开来,生产环境中有利于浏览器缓存,加快二次访问的速度 代码分离的时候,optimization 中配置的 splitChunks 默认就是 async,默认对异步代码进行分离;所以通常情况下能用异步的用异步 import;配合 prefetching 和 preloading 能够产生很好的效果 filename 和 chunkFilename 的区别output: { filename: '[name].js', chunkFilename: '[name].chunk.js'}举个例子 如果入口文件是 main.js 那么打包后生成的文件是 main.js 如果 main.js 中引入了其他模块,比如引入了 lodash 那么可能会生成一个名为 lodash.chunk.js 文件 基本概念了解了,接下来开始对 js 和 css 文件进行分离的操作: js 代码分离js 代码的分离操作,首先要考虑的就是对异步代码的分离。这里使用 dynamicImport dynamicImport可以使用 magic comment 来修改动态 import 导出的 chunkname,语法规则如下: ...

May 18, 2019 · 2 min · jiezi

webpack429x成神之路九-webpackdevserver上

目录 上节:使用loader之打包样式下 首先删除bundles, 删完后目录如下: 之前每次都要 npm run build后才能看打包后的效果,在开发阶段是不可能这么干地,我们需要一个能使代码及时生效的功能。webpack自带的webpack-dev-server 为你提供了一个简单的 web 服务器,并且能够实时重新加载 基本使用修改配置:webpack.config.js: const { resolve } = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');const CleanWebpackPlugin = require('clean-webpack-plugin');module.exports = { mode: 'production', entry: './src/index.js', output: { filename: '[name].[contenthash:8].js', path: resolve(__dirname, 'bundles') }, // 开启devServer devServer: {}, module: { rules: [{ test: /\.(gif|jpg|jpeg|png|svg)$/, use: ['url-loader'] }, { test: /\.less$/, use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader'] }] }, plugins: [ new HtmlWebpackPlugin({ template: './index.html' }), new CleanWebpackPlugin() ]};src/index.js: ...

May 16, 2019 · 2 min · jiezi

babel7实践

前些天使用了 babel7,特来做个笔记。 presets在 babel7 中,已经废弃了之前的阶段性提案,现在统一使用 @babel/preset-env。所以呢,这里倒是省去了一些麻烦。在 webpack 配置中 preset-env 配合 babel-loader 就可以转换 ES2015+ 语法了。同时,官方建议我们使用 targets 设定目标浏览器决定需要兼容的功能。举个例子: module.exports = { presets: [ [ '@babel/preset-env', { targets: { ie: "11" } } ] ]}polyfillpolyfill 在之前都是用来引入新的 api 和功能的。如我们常用的 promise,Object.assign 等。在 babel6 及之前,只需要在入口引入 polyfill 即可。然而这也带来了问题,一次性加载了整个 polyfill,十分冗余。 而用了 babel7 通过简单的配置就可以达成按需加载的目的,我们也不再需要手动引入 polyfill。 useBuiltIns没错,使用这个新的配置项,就可以实现按需加载 polyfill。其值可取以下3个: false值为 false 的时候,相当于没用,这时就得手动引入所有的 polyfill。 entry使用 entry 的时候,也需要手动引入 polyfill,即 import '@babel/polyfill';,同时也引入了所有的 polyfill。这个配置项,总觉得没什么用,如果有老哥知道的话可以在评论区提出一起讨论。 usage值为 usage 的时候,无需引入 polyfill,babel 会自动按需加载需要的功能: { \\... useBuiltIns: 'usage'}如果需要在命令行打印加载项,可以设置 debug: ...

May 15, 2019 · 2 min · jiezi

webpack429x成神之路八-使用loader之打包样式下

目录 上节:使用loader之打包样式上 目录结构如下: postcssPostCSS 是一个允许使用 JS 插件转换样式的工具。 这些插件可以检查(lint)你的 CSS,支持 CSS Variables 和 Mixins, 编译尚未被浏览器广泛支持的先进的 CSS 语法,内联图片,以及其它很多优秀的功能。截止到目前,PostCSS 有 200 多个插件。[官方传送门][3]这里就示范其中一个添加浏览器前缀的插件:autoprefixer 首先浏览器运行上节打包后的代码,即bundles/index.html查看图片样式: 现在css3没有加浏览器前缀,利用autoprefixer可轻松解决这一问题,不需要自己手动添加。首先修改配置;webpack.config.js: // 省略{ test: /\.css$/, use: ['style-loader', { loader: 'css-loader', options: { // 开启模块化 modules: true } }, 'postcss-loader']}// 省略这样css会先经过postcss-loader处理。然后安装插件:npm i postcss-loader autoprefixer -D 再到根目录下新建postcss.config.js,并添加如下代码: module.exports = { plugins: [ require('autoprefixer') ]}然后npm run build,运行打包后的代码,这时应该自动加上前缀了 这些postcss的插件各自都有自己的配置,详细使用可参考官网:https://github.com/postcss/au...for example: module.exports = { plugins: [ require('autoprefixer')({ "browsers": [ "defaults", "not ie < 11", "last 2 versions", "> 1%", "iOS 7", "last 3 iOS versions" ] }) ]};使用预处理器这里以less为例:修改配置webpack.config.js: ...

May 15, 2019 · 1 min · jiezi

vuecli使用webpack代理解决跨域问题

可以在vue-cli创建的项目目录config/index.js,找到dev.proxyTable属性,在上面写代理域名即可

May 15, 2019 · 1 min · jiezi

windows10-下使用webpack创建library

参考: https://github.com/kalcifer/webpack-library-examplehttps://webpack.js.org/guides/author-libraries说明: 最近结合webpack官方文档和示例代码在windows10下使用webpack创建library时遇见一些问题,在此总结一下创建library: 基础知识准备 1. 库使用方法 ES2015 module import: import * as webpackNumbers from 'webpack-numbers'; // ... webpackNumbers.wordToNum('Two'); CommonJS module require: const webpackNumbers = require('webpack-numbers'); // ... webpackNumbers.wordToNum('Two'); AMD module require: require(['webpackNumbers'], function (webpackNumbers) { // ... webpackNumbers.wordToNum('Two'); }); via a <script>: <!doctype html> <html> ... <script src="https://unpkg.com/webpack-numbers"></script> <script> // ... // Global variable webpackNumbers.wordToNum('Five') // Property in the window object window.webpackNumbers.wordToNum('Five') // ... </script> </html> 2. 暴露 library why:为了让你的 library 能够在各种用户环境(consumption)中可用 how: 在output中添加 library属性 当你在 import 引入模块时,这可以将你的 library bundle 暴露为全局变量 在output中添加 libraryTarget 属性 1) 控制 library 以不同方式暴露,让 library 和其他环境兼容 2) 可以通过以下方式暴露 library: 变量:作为一个全局变量,通过 script 标签来访问(libraryTarget:'var') this:通过 this 对象访问(libraryTarget:'this') window:通过 window 对象访问,在浏览器中(libraryTarget:'window') UMD:在 AMD 或 CommonJS 的 require 之后可访问(libraryTarget:'umd') 3) 如果设置了 library 但没设置 libraryTarget,则 libraryTarget 默认为 var。 output.globalObject string: 'window' 要使umd 在浏览器和node.js 上都可用,globalObject需要设置成this 示例: output: { ... library: 'webpackNumbers', libraryTarget: 'umd', globalObject: 'this' } 步骤: ...

May 12, 2019 · 3 min · jiezi

打包优化从0到1搭建element后台框架优化篇

前言hello,咱又见了~~嘻嘻。本次主要来说说这个打包优化的问题。一个vue项目从开发到上线必须得经历打包过程,一个项目的打包优化与否都决定了你这个项目的运行速度以及用户体验。本次主要是针对vue.config,js的配置进行优化。项目地址 开发环境与生产环境开发环境与生产环境的配置也是开发中的必不可少的一环。本项目是由vue-cli3开发,vue-cli3深度集成了webpack,如果不熟悉vue-cli3可以先去官网看看相关配置。 开发环境在项目根目录下新建.env.development文件表明是开发环境。 VUE_APP_CURRENTMODE ="development" //当前的环境 VUE_APP_LOGOUT_URL="http://localhost:3000/" //开发环境的地址生产环境在项目根目录下新建.env.production文件表明是生产环境。 VUE_APP_CURRENTMODE ="development" //当前的环境 VUE_APP_LOGOUT_URL="xxx" //生产环境的地址当然你也可以自己创建一个测试环境.env.test,同样可以像上边一样配置。 环境运用那么接下来我们怎么用它呢?这里不得不说一下的是package.json里面的两个命令serve,build,其实对应的是全命令是vue-cli-service serve --mode development,vue-cli-service build --mode production,如果你想要在构建命令中使用开发环境变量,那么可以加入 "dev-build": "vue-cli-service build --mode development"接下来在vue.config.js运用它。 config.plugin('define').tap(args => { args[0]['process.env'].VUE_APP_LOGOUT_URL = JSON.stringify(process.env.VUE_APP_LOGOUT_URL) console.log(args[0]) return args; });这里有必要说下,这段代码是写在chainWebpack配置项下面。这段代码其实运用了两个webpack插件webpack-chain允许配置链式操作,以及webpack.DefinePlugin。 webpack-chain:尝试通过提供可链式或顺流式的 API 创建和修改webpack 配置。了解更多webpack.DefinePlugin:它的作用是定义全局常量,是常量。即在模块用它定义的全局常量,那么你就不能改变它。也就是说我定义了一个process.env.VUE_APP_LOGOUT_URL常量,在src文件夹下面都可以使用。了解更多分包(code splitting)首先思考,我们引入的第三方包与我们的业务代码一起打包会产生什么问题?顾名思义,我们的业务代码变动比较频繁,而我们引入的第三方包基本上不会变动。浏览器会有缓存,没有变动的文件会直接从缓存中读取,这也间接的优化了网站的访问速速。接下来配置vue.config.js, 分割第三方库 //代码分割 config.optimization.minimize(true); config.optimization.splitChunks({ chunks: 'all', cacheGroup:{ //vue2-editor单独打一个包 vueEdior: { name: 'vueEdior', test: /[\\/]node_modules[\\/]vue2-editor[\\/]/, priority: 10 // 优先级要大于 vendors 不然会被打包进 vendors }, //其余的第三方包打进vendor vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 } } })分割共用文件组件是vue项目的重要组成部分。相当一部分组件都可以公用,在不同的文件中引入,因此我们可以将这部分公用的组件直接分割出来。 ...

May 11, 2019 · 2 min · jiezi

分享

mock服务const fs = require('fs');const path = require('path')const ASYNC_PREFIX = '/async/*'function handerAsyncRequest (req, res) { let data = ''; let reqPath = req.path; let reqQuery = req.query; let protocol = req.protocol; let method = reqQuery['method']; let pathStr = ''; let fileUrl = ''; if (method) { pathStr = method.replace(/\./ig, path.sep) + '.json' } else { pathStr = reqPath.replace(/\/async/ig, '') + '.json' } fileUrl = path.join(__dirname, '..', 'mock', 'data', pathStr) try { data = fs.readFileSync(fileUrl, { encoding: 'utf8' }); } catch (e) { data = e; } res.send(data);}function beforeServer (app, server) { app.get(ASYNC_PREFIX, handerAsyncRequest) app.post(ASYNC_PREFIX, handerAsyncRequest)}module.exports = { beforeServer};app.use(path, router/callback) 也可以实现, path不接受正则,会匹配以path开头的路径webpack配置服务配置devServer: { before: beforeServer}vue-loader.conf.jstransformToRequire: { video: ['src', 'poster'], source: 'src', img: 'src', image: 'xlink:href'}在模板编译过程中,编译器可以将某些特性转换为 require 调用,例如 src 中的 URL。因此这些目标资源可以被 webpack 处理。例如 <img src="./foo.png"> 会找到你文件系统中的 ./foo.png 并将其作为一个依赖包含在你的包里。 ...

May 10, 2019 · 1 min · jiezi

webpack4-js构建速度优化

请注意:本文主要是针对 webpack4 的 js 构建速度做优化。用一句话总结本文,就是给 js 构建流程加 cache,让任务并行。 babel-loader首先第一个主角 babel-loader,给babel-loader 加一个参数即可cacheDirectory: true。相关的配置还有 cacheIdentifier 和 cacheCompression,cacheIdentifier 是给 cache 配一个标识,cacheCompression 是babel-loader 默认会以 gzip 去压缩,如果你的文件量非常大可以尝试设为 false。 thread-loader什么,光有 cahche 还是不够快吗,谁让你一次要改那么多文件。cache 只能在第一次构建之后起作用,而且第一次构建本身也依旧是耗时的事情。那么我们请出第二个主角 thread-loader,这货看名字就知道是干嘛的吧。简单说就是让你的多核 cpu 按一定配置来参与到打包流程中。加进来之后 js rule 的配置就变成以下 rules: [ { test: /\.js$/, include: /(src)/, use: [ { loader: 'thread-loader', options: { workers: os.cpus().length } }, { loader: 'babel-loader', options: { cacheDirectory: true, presets: [['es2015', { modules: false }], 'stage-0', 'react'] } } ] },workers 的数量就是参与编译的 cpu 核心数量。thread-loader 的参数大致可以分为 workers 和 pool 两类: ...

May 10, 2019 · 1 min · jiezi

开发函数计算的正确姿势支持-ES6-语法和-webpack-压缩

首先介绍下在本文出现的几个比较重要的概念: 函数计算(Function Compute): 函数计算是一个事件驱动的服务,通过函数计算,用户无需管理服务器等运行情况,只需编写代码并上传。函数计算准备计算资源,并以弹性伸缩的方式运行用户代码,而用户只需根据实际代码运行所消耗的资源进行付费。函数计算更多信息 参考。Fun: Fun 是一个用于支持 Serverless 应用部署的工具,能帮助您便捷地管理函数计算、API 网关、日志服务等资源。它通过一个资源配置文件(template.yml),协助您进行开发、构建、部署操作。Fun 的更多文档 参考。2.0 版本的 Fun,在部署这一块做了很多努力,并提供了比较完善的功能,能够做到将云资源方便、平滑地部署到云端。但该版本,在本地开发上的体验,还有较多的工作要做。于是,我们决定推出 Fun Init 弥补这一处短板。Fun Init: Fun Init 作为 Fun 的一个子命令存在,只要 Fun 的版本大于等于 2.7.0,即可以直接通过 fun init 命令使用。Fun Init 工具可以根据指定的模板快速的创建函数计算应用,快速体验和开发函数计算相关业务。官方会提供常用的模板,用户也可以自定自己的模板。背景阿里云函数计算是事件驱动的全托管计算服务。通过函数计算,您无需管理服务器等基础设施,只需编写代码并上传。函数计算会为您准备好计算资源,以弹性、可靠的方式运行您的代码,并提供日志查询、性能监控、报警等功能。借助于函数计算,您可以快速构建任何类型的应用和服务,无需管理和运维。而且,您只需要为代码实际运行所消耗的资源付费,代码未运行则不产生费用。 当我们写 nodejs 函数时,函数往往会依赖很多第三方依赖,这样导致函数代码少则几十兆,多则上百兆。代码包太大,会有如下问题: 可能会导致没法成功上传代码到函数计算服务,因为函数计算服务对代码包大小是有限制的,压缩后最大不能超过 50 MB,解压后最大不能超过 250 MB会导致冷启动时间是变大,因为下载代码的过程变大了每次更新代码时间变大另外,函数计算目前只支持 nodejs8 和 nodejs6 这两个版本,这两版本不支持 es6 语法,但是我们可能已经写习惯了 es6 语法该怎么办呢? 熟悉 nodejs 的同学应该知道,项目工程化管理工具 webpack,我们完全可以通过 webpack 将 es6 代码编译成 es5,并且剪切打包压缩成一个 js 文件,然后将该 js 文件上传到函数计算中运行。 快速开始我这里提供了一个 fun 模板,帮助快速搭建一个函数计算 nodejs 项目骨架,支持 es6 代码编译成 es5,并且剪切打包压缩成一个 js 文件,然后将该 js 文件上传到函数计算中运行。操作作步骤如下: ...

May 10, 2019 · 1 min · jiezi

从零开始手写一个优化版的React脚手架Webpack最新版配置

webpack马上要出5了,完全手写一个优化后的脚手架是不可或缺的技能。本文书写时间 2019年5月9日 , webpack版本 4.30.0最新版本要转载必须联系本人经过同意才可转载 谢谢!杜绝5分钟的技术,我们先深入原理再写配置,那会简单很多。实现需求: 识别JSX文件tree shaking 摇树优化 删除掉无用代码PWA功能,热刷新,安装后立即接管浏览器 离线后仍让可以访问网站 还可以在手机上添加网站到桌面使用CSS模块化,不怕命名冲突小图片的base64处理文件后缀省掉jsx js json等实现懒加载,按需加载 , 代码分割支持less sass stylus等预处理code spliting 优化首屏加载时间 不让一个文件体积过大提取公共代码,打包成一个chunk每个chunk有对应的chunkhash,每个文件有对应的contenthash,方便浏览器区别缓存图片压缩CSS压缩增加CSS前缀 兼容各种浏览器对于各种不同文件打包输出指定文件夹下缓存babel的编译结果,加快编译速度每个入口文件,对应一个chunk,打包出来后对应一个文件 也是code spliting删除HTML文件的注释等无用内容每次编译删除旧的打包代码将CSS文件单独抽取出来等等....webpack中文官网的标语是 :让一切都变得简单 概念: 本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。 webpack v4.0.0 开始,可以不用引入一个配置文件。然而,webpack 仍然还是高度可配置的。在开始前你需要先理解四个核心概念: * 入口(`entry`)* 输出(`output`)* `loader`* 插件(`plugins`) `本文旨在给出这些概念的高度概述,同时提供具体概念的详尽相关用例。` 让我们一起来复习一下最基础的Webpack知识,如果你是高手,那么请直接忽略这些往下看吧....入口 入口起点`(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。每个依赖项随即被处理,最后输出到称之为 bundles 的文件中,我们将在下一章节详细讨论这个过程。可以通过在 webpack 配置中配置 entry 属性,来指定一个入口起点(或多个入口起点)。默认值为 ./src。接下来我们看一个 entry 配置的最简单例子: webpack.config.jsmodule.exports = { entry: './path/to/my/entry/file.js'};入口可以是一个对象,也可以是一个纯数组 ...

May 9, 2019 · 5 min · jiezi

从零开始手写一个React脚手架优化版的webpack最新版配置

webpack马上要出5了,完全手写一个优化后的脚手架是不可或缺的技能。本文书写时间 2019年5月9日 , webpack版本 4.30.0最新版本要转载必须联系本人经过同意才可转载 谢谢!杜绝5分钟的技术,我们先深入原理再写配置,那会简单很多。实现需求: 识别JSX文件tree shaking 摇树优化 删除掉无用代码PWA功能,热刷新,安装后立即接管浏览器 离线后仍让可以访问网站 还可以在手机上添加网站到桌面使用CSS模块化,不怕命名冲突小图片的base64处理文件后缀省掉jsx js json等实现懒加载,按需加载 , 代码分割支持less sass stylus等预处理code spliting 优化首屏加载时间 不让一个文件体积过大提取公共代码,打包成一个chunk每个chunk有对应的chunkhash,每个文件有对应的contenthash,方便浏览器缓存图片压缩CSS压缩增加CSS前缀 兼容各种浏览器对于各种不同文件打包输出指定文件夹下缓存babel的编译结果,加快编译速度每个入口文件,对应一个chunk,打包出来后对应一个文件 也是code spliting删除HTML文件的注释等无用内容webpack中文官网的标语是 :让一切都变得简单 概念: 本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。 webpack v4.0.0 开始,可以不用引入一个配置文件。然而,webpack 仍然还是高度可配置的。在开始前你需要先理解四个核心概念: * 入口(`entry`)* 输出(`output`)* `loader`* 插件(`plugins`) `本文旨在给出这些概念的高度概述,同时提供具体概念的详尽相关用例。` 让我们一起来复习一下最基础的Webpack知识,如果你是高手,那么请直接忽略这些往下看吧....入口 入口起点`(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。每个依赖项随即被处理,最后输出到称之为 bundles 的文件中,我们将在下一章节详细讨论这个过程。可以通过在 webpack 配置中配置 entry 属性,来指定一个入口起点(或多个入口起点)。默认值为 ./src。接下来我们看一个 entry 配置的最简单例子: webpack.config.jsmodule.exports = { entry: './path/to/my/entry/file.js'};入口可以是一个对象,也可以是一个纯数组 ...

May 9, 2019 · 3 min · jiezi

Webpack-是怎样运行的

在平时开发中我们经常会用到Webpack这个时下最流行的前端打包工具。它打包开发代码,输出能在各种浏览器运行的代码,提升了开发至发布过程的效率。 我们知道一份Webpack配置文件主要包含入口(entry)、输出文件(output)、模式、加载器(Loader)、插件(Plugin)等几个部分。但如果只需要组织 JS 文件的话,指定入口和输出文件路径即可完成一个迷你项目的打包。下面我们来通过一个简单的项目来看一下Webpack是怎样运行的。 同步加载本文使用 webpack ^4.30.0 作示例.为了更好地观察产出的文件,我们将模式设置为 development 关闭代码压缩,再开启 source-map 支持原始源代码调试。除此之外。我们还简单的写了一个插件MyPlugin来去除源码中的注释。新建src/index.js console.log('Hello webpack!');新建webpack配置文件webpack.config.js const path = require('path');const MyPlugin = require('./src/MyPlugin.js')module.exports = { mode: 'development', devtool: 'source-map', entry: './src/index.js', output: { path: path.resolve(__dirname, 'dist') }, plugins:[ new MyPlugin() ]};新建src/MyPlugin.js。了解webpack插件更多信息 class MyPlugin { constructor(options) { this.options = options this.externalModules = {} } apply(compiler) { var reg = /("([^\\\"]*(\\.)?)*")|('([^\\\']*(\\.)?)*')|(\/{2,}.*?(\r|\n))|(\/\*(\n|.)*?\*\/)|(\/\*\*\*\*\*\*\/)/g compiler.hooks.emit.tap('CodeBeautify', (compilation)=> { Object.keys(compilation.assets).forEach((data)=> { let content = compilation.assets[data].source() // 欲处理的文本 content = content.replace(reg, function (word) { // 去除注释后的文本 return /^\/{2,}/.test(word) || /^\/\*!/.test(word) || /^\/\*{3,}\//.test(word) ? "" : word; }); compilation.assets[data] = { source(){ return content }, size(){ return content.length } } }) }) }}module.exports = MyPlugin现在我们运行命令 webpack --config webpack.config.js ,打包完成后会多出一个输出目录 dist:dist/main.js。main 是 webpack 默认设置的输出文件名,我们快速瞄一眼这个文件: ...

May 9, 2019 · 7 min · jiezi

一图解释webpack编译流程

May 9, 2019 · 0 min · jiezi