├── .babelrc ├── .editorconfig ├── .eslintrc ├── LICENSE ├── package-lock.json ├── package.json ├── postcss.config.js ├── readme.md ├── src ├── App.vue ├── images │ └── logo_my.png ├── index.html ├── index.js ├── router │ └── router.js └── style │ └── index.scss ├── webpack.analy.js ├── webpack.build.js ├── webpack.config.js └── webpack.server.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env"] 3 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "plugins": [ 4 | "react", 5 | "vue" 6 | ], 7 | "parserOptions": { 8 | "ecmaVersion": 6, 9 | "sourceType": "module", 10 | "ecmaFeatures": { 11 | "jsx": true 12 | } 13 | }, 14 | "env": { 15 | "browser": true, 16 | "amd": true, 17 | "es6": true, 18 | "node": true, 19 | "mocha": true 20 | }, 21 | "rules": { 22 | "global-strict": 0, 23 | "no-underscore-dangle": 0, 24 | "no-console": 0, 25 | "no-trailing-spaces": [1, { "skipBlankLines": true }], //不允许在语句后存在多余的空格 26 | "no-alert": 0, 27 | "react/jsx-uses-react": 1, 28 | "react/jsx-uses-vars": 1, 29 | 30 | // allow async-await 31 | "generator-star-spacing": "off", 32 | // allow debugger during development 33 | // "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off", 34 | 35 | "space-before-function-paren": 0, // 强制在 function的左括号之前使用一致的空格 36 | 37 | 38 | 39 | //警告 40 | "quotes": ["warn", "single"], //建议使用单引号 41 | // "no-inner-declarations": [1, "both"], //不建议在{}代码块内部声明变量或函数 42 | "no-extra-boolean-cast": 1, //多余的感叹号转布尔型 43 | "no-extra-semi": 1, //多余的分号 44 | "semi": ["off", "always"], // js语句结尾必须使用分号 45 | "no-extra-parens": 1, //多余的括号 46 | "no-empty": 1, //空代码块 47 | "no-use-before-define": [1, "nofunc"], //使用前未定义 48 | "complexity": [1, 25], //圈复杂度大于25 警告 49 | 50 | 51 | 52 | //常见错误 53 | "comma-dangle": [0, "never"], //定义数组或对象最后多余的逗号 54 | // "no-debugger": 2, //debugger 调试代码未删除 55 | "no-constant-condition": 2, //常量作为条件 56 | "no-dupe-args": 2, //参数重复 57 | "no-dupe-keys": 2, //对象属性重复 58 | "no-duplicate-case": 2, //case重复 59 | "no-empty-character-class": 2, //正则无法匹配任何值 60 | "no-invalid-regexp": 2, //无效的正则 61 | "no-func-assign": 2, //函数被赋值 62 | "valid-typeof": 2, //无效的类型判断 63 | "no-unreachable": 2, //不可能执行到的代码 64 | "no-unexpected-multiline": 1, //行尾缺少分号可能导致一些意外情况 65 | "no-sparse-arrays": 2, //数组中多出逗号 66 | "no-shadow-restricted-names": 2, //关键词与命名冲突 67 | "no-undef": 2, //变量未定义 68 | "no-unused-vars": 0, //变量定义后未使用 69 | "no-cond-assign": 2, //条件语句中禁止赋值操作 70 | "no-native-reassign": 2, //禁止覆盖原生对象 71 | 72 | //代码风格优化 73 | "no-else-return": 1, //在else代码块中return,else是多余的 74 | "no-multi-spaces": 1, //不允许多个空格 75 | "key-spacing": [1, {"beforeColon": false, "afterColon": true}],//object直接量建议写法 : 后一个空格签名不留空格 76 | "block-scoped-var": 1, //变量定义后未使用 77 | "consistent-return": 1, //函数返回值可能是不同类型 78 | "accessor-pairs": 2, //object getter/setter方法需要成对出现 79 | "dot-location": [2, "property"], //换行调用对象方法 点操作符应写在行首 80 | "no-lone-blocks": 0, //多余的{}嵌套 81 | "no-empty-label": 0, //无用的标记 82 | "no-extend-native": 2, //禁止扩展原生对象 83 | "no-floating-decimal": 2, //浮点型需要写全 禁止.1 或 2.写法 84 | "no-loop-func": 2, //禁止在循环体中定义函数 85 | "no-new-func": 2, //禁止new Function(...) 写法 86 | "no-self-compare": 2, //不允与自己比较作为条件 87 | "no-sequences": 2, //禁止可能导致结果不明确的逗号操作符 88 | "no-throw-literal": 2, //禁止抛出一个直接量 应是Error对象 89 | "no-return-assign": [2, "always"], //不允return时有赋值操作 90 | "no-redeclare": [2, {"builtinGlobals": true}],//不允许重复声明 91 | "no-unused-expressions": [2, {"allowShortCircuit": true, "allowTernary": true}],//未使用的表达式 92 | "no-useless-call": 2, //无意义的函数call或apply 93 | "no-useless-concat": 2, //无意义的string concat 94 | "no-void": 2, //禁用void 95 | "no-with": 2, //禁用with 96 | "no-warning-comments": [1, { "terms": ["fixme", "any other term"], "location": "anywhere" }],//标记未写注释 97 | "curly": 2, //if、else、while、for代码块用{}包围 98 | "one-var": 0, 99 | "no-multiple-empty-lines": [1, {"max": 4, "maxEOF": 3}], //空行 最多三行 100 | 101 | //工程化配置 102 | // "prettier.singleQuote": 1, // 防止格式化代码后单引号变双引号 103 | // "update.channel": 1, // 配置是否从更新通道接收自动更新。更改后需要重启。 104 | // "files.autoSaveDelay": 1500, // 保存延时 intellij webstrom 默认制动保存 105 | // "files.autoSave": "afterDelay" // 文件自动保存 106 | 107 | // "eslint.autoFixOnSave": false, // ESLint 自动修复 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 zhoulujun.cn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack4-vue2-project-template", 3 | "version": "2.0.0", 4 | "description": "webpack4 vue2 sass标准模板工程", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "webpack --mode development", 8 | "build": "rm -r dist & webpack --mode production", 9 | "dist": "rm -r dist & webpack --config webpack.build.js", 10 | "analy": "webpack --config webpack.analy.js", 11 | "start": "node webpack.server.js", 12 | "test": "echo \"Error: no test specified\" && exit 1", 13 | "clean": "rm -r dist/*" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/zhoulujun/webpack4-vue2-project-template.git" 18 | }, 19 | "keywords": [ 20 | "webpack4", 21 | "sass", 22 | "vue2", 23 | "project" 24 | ], 25 | "author": "zhoulujun.cn", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/zhoulujun/webpack4-vue2-project-template/issues" 29 | }, 30 | "homepage": "https://github.com/zhoulujun/webpack4-vue2-project-template#readme", 31 | "devDependencies": { 32 | "@babel/core": "^7.2.2", 33 | "@babel/preset-env": "^7.2.3", 34 | "autoprefixer": "^9.4.4", 35 | "babel-eslint": "^10.0.1", 36 | "babel-loader": "^8.0.4", 37 | "css-loader": "^2.1.0", 38 | "eslint": "^5.12.0", 39 | "eslint-loader": "^2.1.1", 40 | "eslint-plugin-react": "^7.12.3", 41 | "eslint-plugin-vue": "^5.1.0", 42 | "file-loader": "^3.0.1", 43 | "happypack": "^5.0.1", 44 | "html-loader": "^0.5.5", 45 | "html-webpack-plugin": "^3.2.0", 46 | "image-webpack-loader": "^4.6.0", 47 | "less": "^3.9.0", 48 | "less-loader": "^4.1.0", 49 | "mini-css-extract-plugin": "^0.5.0", 50 | "open": "0.0.5", 51 | "postcss": "^7.0.7", 52 | "postcss-loader": "^3.0.0", 53 | "sass.js": "^0.11.0", 54 | "sassjs-loader": "^2.0.0", 55 | "style-loader": "^0.23.1", 56 | "url-loader": "^1.1.2", 57 | "vue": "^2.5.21", 58 | "vue-loader": "^15.4.2", 59 | "vue-router": "^3.0.2", 60 | "vue-style-loader": "^4.1.2", 61 | "vue-template-compiler": "^2.5.21", 62 | "webpack": "^4.28.3", 63 | "webpack-assets-manifest": "^3.1.1", 64 | "webpack-bundle-analyzer": "^3.0.3", 65 | "webpack-cli": "^3.2.0", 66 | "webpack-dev-server": "^3.1.14", 67 | "webpack-sftp-client": "^1.2.1", 68 | "webpack-subresource-integrity": "^1.3.1" 69 | }, 70 | "dependencies": { 71 | "sass": "^1.21.0" 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | *@author Create by zhoulujun.cn on 1/7/192:59 PM 3 | *@version 1.0.0 4 | */ 5 | 6 | /*module.exports = { 7 | plugins: { 8 | 'autoprefixer': { 9 | browsers: [ 10 | "> 1%", 11 | "last 5 versions", 12 | "not ie <= 9", 13 | "ios >= 8", 14 | "android >= 4.0" 15 | ] 16 | } 17 | } 18 | };*/ 19 | 20 | module.exports = { 21 | plugins: [ 22 | require('autoprefixer')({ 23 | browsers: [ 24 | "> 1%", 25 | "last 105 versions", 26 | "not ie <= 8", 27 | "ios >= 8", 28 | "android >= 4.0" 29 | ] 30 | }) 31 | ] 32 | }; -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | webpack4 sass babel vue2 标准工程模板 2 | 但是,webpack4还是需要n多优化部分,配置下来,实为不易。而实际开发也不需要浪费这个时间——了解即可 3 | > webpack 一直以来最饱受诟病的就是其配置门槛极高,配置内容极其复杂和繁琐,容易让人从入门到放弃,而它的后起之秀如 rollup、parcel 等均在配置流程上做了极大的优化,做到开箱即用,所以webpack 4 也从中借鉴了不少经验来提升自身的配置效率。愿世间再也不需要 webpack 配置工程师。 4 | 5 | 6 | 目前node-sass sass-loader 替换为 sass.js 与sassjs-loader 免除node-sass 安装困难的烦恼 7 | 8 | 9 | 启动: 10 | ```bash 11 | npm run start 12 | ``` 13 | 打包: 14 | ```bash 15 | npm run build 16 | ``` 17 | 18 | 19 | 20 | 21 | 22 | # 目录结构 23 | 24 | # 团队规范 25 | 遵从平台发布前端规范标准,节选以下要点: 26 | 27 | ## 命名规范 28 | 遵从Camel命名 29 | 30 | ### 变量命名规范: 31 | 32 | #### js规范,请遵从eslint 33 | + 常量全部大写,单词间下划线分隔 34 | + 类采用Pascal命名 35 | ### scss 规范 36 | + css 按照工程结构 嵌套书写,嵌套层级不超过三层——采用 @at-root 37 | + 非页面引用scss文件,加前缀 _ 如:_fun.scss _mixin.scss 38 | 39 | # 构建过程 节选关键步骤 40 | ### 构建目录初始化 41 | ```bash 42 | mkdir yourFileName 43 | cd yourFileName 44 | ``` 45 | 根据工程目录结构,构建相关文件 46 | …… 47 | ___ 48 | ```bash 49 | npm init 50 | npm install webpack webpack-cli --save-dev 51 | ``` 52 | ##### 注:--save-dev和--save的区别: 53 | development很明显就是我们开发所需要的依赖包,而打包好上线的话是不需要这些包的,一来各种包加起来太大,二来它只是我们开发提高效率的工具而已; 54 | 由于本工程只在本地跑,最终还是sftp自动dist 到服务器,所以暂略 55 | 56 | 修改package.json ,npm run dev 检查打包结果 57 | ```json 58 | { 59 | "scripts": { 60 | "dev": "webpack --mode development", 61 | "build": "webpack --mode production" 62 | } 63 | } 64 | ``` 65 | ##### 注:webpack4只需要一个--mode选项 指定 production||development 66 | 参考http://www.ruanyifeng.com/blog/2016/10/npm_scripts.html 67 | +如果是并行执行(即同时的平行执行),可以使用&符号。 68 | +如果是继发执行(即只有前一个任务成功,才执行下一个任务),可以使用&&符号。 69 | npm run script1.js & npm run script2.js 70 | npm run script1.js && npm run script2.js 71 | 72 | 73 | ___ 74 | #### 配置webpack配置文件 webpack.config.js 75 | ##### rule对象参数说明 76 | + test: A condition that must be met 必须满足的条件 77 | + exclude: A condition that must not be met 不能满足的条件 78 | + include: A condition that must be met 必须满足的条件 79 | + loader: A string of “!” separated loaders 用 “!”分割loaders 80 | + loaders: An array of loaders as string loaders的字符串数组 81 | 82 | #### 基础loader 83 | 84 | ```bash 85 | npm install css-loader style-loader html-loader url-loader file-loader --save-dev 86 | ``` 87 | 88 | ```javascript 89 | [ 90 | { 91 | test: /\.html$/, 92 | use: 'html-loader' 93 | }, 94 | { 95 | test: /\.css$/, 96 | use: [ 97 | { 98 | loader: 'style-loader', 99 | options:{ 100 | // singleton:true //处理为单个style标签 101 | } 102 | }, 103 | { 104 | loader: 'css-loader', 105 | options:{ 106 | // minimize:true //压缩css 107 | } 108 | } 109 | ] 110 | }, 111 | { 112 | test:/\.(png|jpg|jpeg|gif)$/,//图片处理 113 | use:[ 114 | { 115 | loader: 'url-loader', 116 | options:{ 117 | limit:2048, 118 | name:'[name][hash].[ext]' 119 | } 120 | }, 121 | { 122 | loader: 'file-loader', 123 | publicPath:publicPath, 124 | outputPath: 'dist/', 125 | useRelativePath: true 126 | } 127 | ] 128 | }, 129 | { 130 | test: /\.(woff|woff2|eot|ttf|otf)$/,//字体处理 131 | use: ['url-loader'] 132 | }, 133 | 134 | ] 135 | ``` 136 | #### 配置babel 编译js 137 | ```bash 138 | npm install --save-dev babel-loader @babel/core @babel/preset-env 139 | ``` 140 | 141 | ```javascript 142 | [ 143 | { 144 | test: /\.js$/, 145 | loader: 'babel-loader', 146 | exclude: /node_modules/ //设置node_modules里的js文件不用解析 147 | } 148 | ] 149 | ``` 150 | 151 | 参考:https://segmentfault.com/a/1190000010468759 152 | 153 | babel7.0后,需要@ @babel/core vs babel-core babel插件和版本需要对应上,不然掉坑 154 | 参考https://www.w3ctech.com/topic/2150 155 | babel-preset-es2015 babel-plugin-transform-runtime babel-plugin-add-module-exports babel-plugin-transform-runtime babel-plugin-transform-class-properties 156 | 157 | #### 配置eslint 检查 158 | 159 | ```bash 160 | npm install --save-dev eslint eslint-loader babel-eslint eslint-plugin-react eslint-plugin-vue 161 | ``` 162 | 163 | ```javascript 164 | [ 165 | {//eslint 检查 166 | test: /\.(js|jsx)$/, 167 | enforce: 'pre', 168 | loader: ['eslint-loader'], 169 | exclude: /node_modules/ //设置node_modules里的js文件不用解析 170 | }, 171 | ] 172 | ``` 173 | 增加.eslintrc配置 174 | ##### 其实没有多大必要,intellij 会自动检车eslint 175 | 176 | #### 处理html 177 | npm install html-webpack-plugin 178 | ```javascript 179 | new HtmlWebpackPlugin({ 180 | filename: './index.html',//输出文件 181 | template: 'src/index.html',//模板文件 182 | inject: 'body',//插入位置 183 | chunks: ['index'], 184 | hash: true, 185 | minify: { 186 | caseSensitive:false, 187 | removeComment:true,//移除注释 188 | collapseWhitespace:false//移除多余空格 189 | } 190 | }) 191 | ``` 192 | #### 处理图片 - 压缩图片 193 | 参考:http://shirmy.me/2018/05/15/webpack-图片、文件处理/ 194 | ```bash 195 | npm install image-webpack-loader --save-dev 196 | ``` 197 | 198 | ```javascript 199 | [ 200 | { 201 | test: /\.(png|jpg|jpeg|gif)$/i,//图片处理 202 | use: [ 203 | { 204 | loader: 'url-loader', 205 | options: { 206 | limit: 0,//图片不转base64,增加css的阻塞时间,开启http2,所以也不用雪碧图 207 | name: '[name].[hash:5].[ext]', 208 | } 209 | }, 210 | ] 211 | }, 212 | {//压缩图片 213 | loader: 'image-webpack-loader', 214 | options: { 215 | bypassOnDebug: true, 216 | } 217 | }, 218 | ] 219 | ``` 220 | 221 | 222 | 223 | #### 配置webapck server 224 | ```bash 225 | npm install webpack-dev-server open --save-dev 226 | ``` 227 | 参看 webpack.server.js 注释 228 | 229 | "start": "node webpack.server.js", 230 | npm start 启动项目 231 | 232 | ### 配置css优化设置 233 | 234 | ```bash 235 | npm install --save-dev postcss-loader autoprefixer postcss autoprefixer mini-css-extract-plugin 236 | ``` 237 | ##### 注: 238 | + webpack4已经废弃 extract-text-webpack-plugin 这个插件了,现在使用的是 mini-css-extract-plugin 239 | + 在项目根目录新建postcss.config.js文件,并对postcss进行配置: 240 | ```javascript 241 | module.exports = { 242 | plugins: { 243 | 'autoprefixer': { 244 | browsers: [ 245 | "> 1%", 246 | "last 5 versions", 247 | "not ie <= 9", 248 | "ios >= 8", 249 | "android >= 4.0" 250 | ] 251 | } 252 | } 253 | }; 254 | ``` 255 | 不然会报出:Error: No PostCSS Config found 256 | 257 | #### 自动消除冗余的css代码 258 | ```bash 259 | npm install --save-dev optimize-css-assets-webpack-plugin 260 | ``` 261 | ##### 个人觉得css压缩优化空间不大,nginx开启gzip的情况,很有限,有点画蛇添足 262 | #### 配置sass 263 | ```bash 264 | npm install --save-dev node-sass sass-loader 265 | 266 | ``` 267 | 但是node-sass 是个坑货 268 | 所以最好换位 269 | ```bash 270 | $ npm install --save-dev sassjs-loader sass.js 271 | 272 | ``` 273 | https://www.npmjs.com/package/sass 274 | 275 | https://www.npmjs.com/package/sassjs-loader 276 | 277 | 278 | ## webpack构建优化 279 | 280 | #### 多线程 happypack 281 | 282 | ```bash 283 | npm install --save-dev happypack 284 | 285 | ``` 286 | 287 | 配置第三方包,比如jquery 288 | ```bash 289 | npm install imports-loader --save-dev 290 | ``` 291 | ```javascript 292 | [ 293 | { 294 | loader: 'imports-loader', 295 | options: { 296 | // 模块为 value,同样webpack也会解析它,如果没有则从alias中解析它 297 | $: 'jquery' 298 | } 299 | } 300 | ] 301 | ``` 302 | #### 增加manifest.json 配置,缓存校对下载, 增加js integrity 安全校验 303 | ```bash 304 | npm install --save-dev webpack-subresource-integrity webpack-assets-manifest 305 | ``` 306 | 两个插件准备写成一个,看来不到春节没有时间 307 | 308 | 309 | #### 增加webpack 模块分析 310 | ```bash 311 | npm install --save-dev webpack-bundle-analyzer 312 | ``` 313 | 配置参看 webpack.analy 314 | 参考文章:https://www.cnblogs.com/ssh-007/p/7944491.html 315 | 316 | #### 增加上传至服务器 317 | ```bash 318 | npm install --save-dev webpack-sftp-client 319 | ``` 320 | 321 | 322 | 323 | 324 | 325 | #### 配置vue 326 | ```bash 327 | npm install --save-dev vue vue-router vue-loader vue-template-compiler vue-style-loader 328 | ``` 329 | 330 | ```javascript 331 | [ 332 | { 333 | test: /\.vue$/, 334 | use: 'vue-loader' 335 | }, 336 | ] 337 | ``` 338 | 339 | 340 | 341 | 342 | 343 | webpack 相关优化,可参看:https://www.zhoulujun.cn/html/tools/webpack/2016_0218_7492.html 344 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 28 | 29 | 32 | -------------------------------------------------------------------------------- /src/images/logo_my.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhoulujun/webpack4-vue2-project-template/9398a1e2d08c9de94bdc05756c4be86b72190769/src/images/logo_my.png -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | webpack4-vue2-project-template 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | *@author Create by zhoulujun.cn on 1/4/1910:30 AM 3 | *@version 1.0.0 4 | */ 5 | import "./style/index.scss"; 6 | 7 | import Vue from 'vue/dist/vue.common';//这是个坑 非:'vue' 8 | import App from './App'; 9 | new Vue({ 10 | el:'#app', 11 | render:h=>h(App) 12 | }); -------------------------------------------------------------------------------- /src/router/router.js: -------------------------------------------------------------------------------- 1 | /** 2 | *@author Create by zhoulujun.cn on 1/7/196:05 PM 3 | *@version 1.0.0 4 | */ 5 | import App from '../App.vue'; 6 | -------------------------------------------------------------------------------- /src/style/index.scss: -------------------------------------------------------------------------------- 1 | .demo{ 2 | width: 146px; 3 | height: 49px; 4 | background: url("../images/logo_my.png"); 5 | background-size: 100%; 6 | transform-origin: 100%; 7 | transform: scale(.5); 8 | display: -webkit-box; 9 | 10 | } 11 | 12 | .page { 13 | display: grid; 14 | grid-gap: 33px; 15 | grid-template: 16 | "head head head" 1fr 17 | "nav main main" minmax(100px, 1fr) 18 | "nav foot foot" 2fr / 19 | 1fr 100px 1fr; 20 | } 21 | .page__head { 22 | grid-area: head; 23 | } 24 | .page__nav { 25 | grid-area: nav; 26 | } 27 | .page__main { 28 | grid-area: main; 29 | } 30 | .page__footer { 31 | grid-area: foot; 32 | } -------------------------------------------------------------------------------- /webpack.analy.js: -------------------------------------------------------------------------------- 1 | /** 2 | *@author Create by zhoulujun.cn on 1/4/1910:30 AM 3 | *@version 1.0.0 4 | *webpack 打包配置 5 | *打包速度方面优化无必要。可能你研究了半天,改了一堆参数发现其实也就提升了几秒,但维护成本上去了,得不偿失。 6 | */ 7 | 8 | 9 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; 10 | 11 | const config = require('./webpack.config'); 12 | 13 | config.plugins.push( 14 | new BundleAnalyzerPlugin() 15 | 16 | ); 17 | 18 | module.exports = config; 19 | -------------------------------------------------------------------------------- /webpack.build.js: -------------------------------------------------------------------------------- 1 | /** 2 | *@author Create by zhoulujun.cn on 1/4/1910:30 AM 3 | *@version 1.0.0 4 | *webpack 打包配置 5 | *打包速度方面优化无必要。可能你研究了半天,改了一堆参数发现其实也就提升了几秒,但维护成本上去了,得不偿失。 6 | */ 7 | 8 | 9 | // const ManifestPlugin = require('webpack-manifest-plugin'); 10 | const WebpackAssetsManifest = require('webpack-assets-manifest'); 11 | const WebpackSubresourceIntegrity = require('webpack-subresource-integrity'); 12 | const WebpackSftpClient = require('webpack-sftp-client'); 13 | 14 | 15 | const config = require('./webpack.config'); 16 | 17 | process.env.NODE_ENV = 'production'; 18 | config.mode = 'production'; 19 | // config.output.publicPath='http://zhoulujun.cn/demo/'; 20 | 21 | config.optimization = { 22 | splitChunks: { // 打包 node_modules里的代码 23 | chunks: 'initial', // 只对入口文件处理 24 | cacheGroups: { 25 | commons: { 26 | chunks: 'initial',//打包初始时依赖第三方 27 | name:'commons', 28 | minChunks: 2,//最小共用次数 29 | maxInitialRequests: 5, 30 | minSize: 0 31 | }, 32 | vendor: { // split `node_modules`目录下被打包的代码到 `page/vendor.js && .css` 没找到可打包文件的话,则没有。 33 | test: /node_modules/, 34 | chunks: 'initial', 35 | name: 'vendor', 36 | priority: 10, 37 | enforce: true 38 | } 39 | } 40 | }, 41 | runtimeChunk: {name:'runtime'}// 单独抽离 runtimeChunk 之后,每次打包都会生成一个runtimeChunk.xxx.js。 42 | }; 43 | 44 | config.plugins.push( 45 | new WebpackAssetsManifest({ 46 | // Options go here 47 | integrity: true, 48 | integrityHashes: ['sha256', 'sha384'] 49 | }), 50 | new WebpackSubresourceIntegrity({ 51 | hashFuncNames: ['sha256', 'sha384'] 52 | }), 53 | 54 | /*new webpack.optimize.UglifyJsPlugin(), 55 | new webpack.optimize.OccurenceOrderPlugin(), 56 | new webpack.optimize.AggressiveMergingPlugin(), 57 | new webpack.NoErrorsPlugin()*/ 58 | 59 | //上传到服务器发布 60 | /*new WebpackSftpClient({ 61 | port: '20020', 62 | host: '10.111.111.38', 63 | username: 'nginx', 64 | password: 'zlj@123', 65 | path: './dist/',//本地上传目录 66 | remotePath: '/usr/local/nginx/html/demo',//服务器目标目录 67 | verbose: true 68 | })*/ 69 | ); 70 | 71 | module.exports = config; 72 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | *@author Create by zhoulujun.cn on 1/4/1910:30 AM 3 | *@version 1.0.0 4 | * webpack 配置文件 5 | */ 6 | 'use strict'; 7 | const path = require('path'); 8 | const os = require('os'); 9 | const HappyPack = require('happypack'); 10 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 11 | const {VueLoaderPlugin} = require('vue-loader'); 12 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 13 | const devMode = process.env.NODE_ENV === 'development'; 14 | const happyThreadPool = HappyPack.ThreadPool({size: os.cpus().length}); 15 | const publicPath = ''; 16 | console.log('devMode___________', devMode); 17 | const config = { 18 | // target: 'web',//告知 webpack 为目标(target)指定一个环境。默认web 19 | entry: {//配置页面入口 20 | index: './src/index.js' 21 | }, 22 | output: { //配置输出选项 23 | path: path.resolve(__dirname, 'dist'),//输出路径为,当前路径下 24 | filename: '[name].[hash:5].js'//输出后的文件名称 25 | }, 26 | resolve: { 27 | extensions: ['.js', '.json', '.vue'] //减少文件查找 28 | }, 29 | 30 | module: { 31 | rules: [ 32 | { 33 | test: /\.html$/, 34 | use: 'html-loader' 35 | }, 36 | { 37 | test: /\.css$/, 38 | use: [//使用use可配置多个loader进行处理。顺序由最后一个至第一个。此处匹配到css文件后,先由postcss-loader处理,css-loader处理后再交由style-loader处理 39 | 'vue-style-loader',//将样式通过style标签的方式加入到dom中 40 | devMode ? { 41 | loader: 'style-loader', 42 | options: { 43 | // singleton:true //处理为单个style标签 44 | } 45 | } : 46 | MiniCssExtractPlugin.loader, 47 | {//css-loader 解释(interpret) @import 和 url() 48 | loader: 'css-loader', 49 | options: { 50 | // url:false, //false css中加载图片的路径将不会被解析 不会改变 51 | // minimize:true, //压缩css 52 | importLoaders: 1//importLoaders代表import进来的资源;2代表css-loader后还需要使用几个loader 53 | } 54 | }, 55 | {//需在css-loader/style-loader后面,在其他预处理前面 56 | loader: 'postcss-loader', 57 | options: { 58 | 59 | plugins: [ 60 | require('autoprefixer') 61 | ], 62 | browsers: [ 63 | '> 1%', 64 | 'last 5 versions', 65 | 'not ie <= 9', 66 | 'ios >= 8', 67 | 'android >= 4.0' 68 | ] 69 | } 70 | } 71 | ] 72 | }, 73 | { //sass文件。vue中会将使用sass写的样式抛出给该rule处理.vue中lang可以设置为sass/scss,只需将两者类型都匹配到sass就行 74 | test: /\.(scss)$/, 75 | use: [//使用use可配置多个loader进行处理。顺序由最后一个至第一个。此处匹配到css文件后,先由css-loader进行处理,css-loader处理后再交由vue-style-loader处理 76 | 'vue-style-loader',//将样式通过style标签的方式加入到dom中 77 | devMode ? { 78 | loader: 'style-loader' 79 | /* options: { 80 | singleton:true //处理为单个style标签 81 | }*/ 82 | } : 83 | MiniCssExtractPlugin.loader, 84 | {//css-loader 解释(interpret) @import 和 url() 85 | loader: 'css-loader', 86 | options: { 87 | // url:false, //false css中加载图片的路径将不会被解析 不会改变 88 | // minimize:true, //压缩css 89 | importLoaders: 1, 90 | sourceMap: devMode//importLoaders代表import进来的资源;2代表css-loader后还需要使用几个loader 91 | } 92 | }, 93 | {//需在css-loader/style-loader后面,在其他预处理前面 94 | loader: 'postcss-loader', 95 | options: { 96 | 97 | plugins: [ 98 | require('autoprefixer') 99 | ], 100 | browsers: [ 101 | '> 1%', 102 | 'last 5 versions', 103 | 'not ie <= 9', 104 | 'ios >= 8', 105 | 'android >= 4.0' 106 | ], 107 | sourceMap: devMode 108 | } 109 | }, 110 | { 111 | loader: 'sassjs-loader' 112 | 113 | } 114 | ] 115 | }, 116 | { //less。vue中会将使用sass写的样式抛出给该rule处理.vue中lang可以设置为sass/scss,只需将两者类型都匹配到sass就行 117 | test: /\.(less)$/, 118 | use: [//使用use可配置多个loader进行处理。顺序由最后一个至第一个。此处匹配到css文件后,先由css-loader进行处理,css-loader处理后再交由vue-style-loader处理 119 | 'vue-style-loader',//将样式通过style标签的方式加入到dom中 120 | 'style-loader' 121 | ] 122 | }, 123 | 124 | { 125 | test: /\.(png|jpg|jpeg|gif)$/,//图片处理 126 | use: [ 127 | { 128 | loader: 'url-loader', 129 | options: { 130 | limit: 50,//图片不转base64,减少css的阻塞时间,开启http2,所以也不用雪碧图 131 | name: '[name].[hash:5].[ext]', 132 | url: false,//不处理css图片路径, 133 | outputPath: 'images' 134 | } 135 | } 136 | ] 137 | }, 138 | 139 | {//压缩图片 140 | loader: 'image-webpack-loader', 141 | options: { 142 | bypassOnDebug: true 143 | } 144 | }, 145 | { 146 | test: /\.(woff|woff2|eot|ttf|otf)$/,//字体处理 147 | use: ['url-loader'] 148 | }, 149 | 150 | {//babel编译 151 | test: /\.js$/, 152 | loader: ['happypack/loader?id=js'], 153 | exclude: /node_modules/ //设置node_modules里的js文件不用解析 154 | }, 155 | 156 | {//eslint 检查 157 | test: /\.(js|jsx)$/, 158 | enforce: 'pre', 159 | loader: ['eslint-loader'], 160 | exclude: /node_modules/ //设置node_modules里的js文件不用解析 161 | }, 162 | { 163 | test: /\.vue$/, 164 | loader: 'vue-loader' 165 | } 166 | 167 | ] 168 | }, 169 | plugins: [ 170 | 171 | new HappyPack({ 172 | id: 'js',//用id来标识 happypack处理那里类文件 173 | threadPool: happyThreadPool, //共享进程池 174 | loaders: [ 175 | { 176 | loader: 'babel-loader' 177 | } 178 | ] 179 | }), 180 | new HappyPack({ 181 | id: 'scss',//用id来标识 happypack处理那里类文件 182 | threadPool: happyThreadPool, //共享进程池 183 | loaders: [ 184 | { 185 | loader: 'sassjs-loader' 186 | } 187 | ] 188 | }), 189 | new HappyPack({ 190 | id: 'less',//用id来标识 happypack处理那里类文件 191 | threadPool: happyThreadPool, //共享进程池 192 | loaders: [ 193 | { 194 | loader: 'less-loader' 195 | } 196 | ] 197 | }), 198 | 199 | new VueLoaderPlugin(), 200 | 201 | new MiniCssExtractPlugin({ 202 | filename: '[name].[hash:5].css', 203 | chunkFilename: '[id].[hash].css', 204 | disable: false, //是否禁用此插件 205 | allChunks: true 206 | }), 207 | 208 | new HtmlWebpackPlugin({ 209 | template: './src/index.html',//本地模板文件的位置,支持加载器(如handlebars、ejs、undersore、html等),如比如 handlebars!src/index.hbs; 210 | filename: './index.html',//输出文件的文件名称,默认为index.html,不配置就是该文件名;此外,还可以为输出文件指定目录位置(例如'html/index.html') 211 | chunks: ['index','vendor','commons','manifest'], 212 | inject: true,//1、true或者body:所有JavaScript资源插入到body元素的底部2、head: 所有JavaScript资源插入到head元素中3、false: 所有静态资源css和JavaScript都不会注入到模板文件中 213 | showErrors: true,//是否将错误信息输出到html页面中 214 | hash: false,//是否为所有注入的静态资源添加webpack每次编译产生的唯一hash值 215 | favicon: '',//添加特定的 favicon 路径到输出的 HTML 文件中。 216 | minify: { 217 | caseSensitive: false, 218 | removeComment: true,//移除注释 219 | collapseWhitespace: false//移除多余空格 220 | } 221 | }) 222 | ] 223 | }; 224 | 225 | module.exports = config; 226 | -------------------------------------------------------------------------------- /webpack.server.js: -------------------------------------------------------------------------------- 1 | /** 2 | *@author Create by zhoulujun.cn on 1/4/1910:30 AM 3 | *@version 1.0.0 4 | * webpack server 配置 5 | */ 6 | const webpack = require('webpack'); 7 | const WebpackDevServer = require('webpack-dev-server'); 8 | const open = require('open'); 9 | 10 | const config = require('./webpack.config'); 11 | 12 | process.env.NODE_ENV='development'; 13 | config.mode = 'development'; 14 | config.devtool='cheap-module-eval-source-map'; 15 | 16 | config.plugins.push( 17 | new webpack.HotModuleReplacementPlugin(),//热替换 18 | new webpack.NoEmitOnErrorsPlugin(),//去除系统抛出的错误消息 19 | ); 20 | 21 | 22 | const addressObj = { 23 | ip: getLocalIPAdress(), 24 | port: 11036 25 | }; 26 | 27 | new WebpackDevServer(webpack(config), { 28 | 29 | historyApiFallback: true, 30 | hot: true,//热加载 31 | hotOnly: true, 32 | overlay: { 33 | errors: true//webpack编译出现的错误是否会出现在网页中 34 | }, 35 | compress: false, 36 | proxy: { 37 | '/api/*': { 38 | target: 'https://zhoulujun.cn/api',//代理地址 39 | secure: false 40 | } 41 | } 42 | }) 43 | .listen(addressObj.port,addressObj.ip,function (error) { 44 | error&&console.log(error); 45 | let address=`http://${addressObj.ip}:${addressObj.port}`; 46 | // let address=`http://localhost:13080`; 47 | open(address); 48 | console.log('listening at:'+address) 49 | }); 50 | 51 | function getLocalIPAdress () { 52 | var interfaces = require('os').networkInterfaces(); 53 | for (let devName in interfaces) { 54 | let iface = interfaces[devName]; 55 | for (let i = 0; i < iface.length; i++) { 56 | let alias = iface[i]; 57 | if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) { 58 | return alias.address; 59 | } 60 | } 61 | } 62 | return 'localhost'; 63 | } 64 | --------------------------------------------------------------------------------