├── .npmrc ├── app ├── libs │ ├── test.css │ ├── utils.js │ └── common.js ├── templates │ ├── test │ │ ├── html │ │ │ └── index.pug │ │ ├── css │ │ │ └── index.css │ │ └── index.js │ └── test0 │ │ ├── html │ │ └── index.pug │ │ ├── index.js │ │ └── css │ │ └── index.css └── static │ ├── js │ └── test │ │ └── index.js │ └── img │ └── 1.jpg ├── .gitignore ├── .eslintignore ├── .babelrc ├── test ├── mocks │ └── demo.js └── unit │ └── demo.spec.js ├── postcss.config.js ├── .travis.yml ├── webpack.config.js ├── config ├── config.js ├── webpack.config.product.js ├── webpack.config.dev.js ├── webpack.config.lint.js └── webpack.config.base.js ├── .editorconfig ├── .eslintrc.js ├── package.json ├── karma.conf.js └── README.md /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false -------------------------------------------------------------------------------- /app/libs/test.css: -------------------------------------------------------------------------------- 1 | a { 2 | color: #ddd 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | npm-debug.log 4 | coverage 5 | -------------------------------------------------------------------------------- /app/templates/test/html/index.pug: -------------------------------------------------------------------------------- 1 | h1 TEST PAGE 2 | a(href="") 哈哈哈哈哈 3 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | bin 3 | node_modules 4 | logs 5 | karam.conf.js 6 | -------------------------------------------------------------------------------- /app/templates/test0/html/index.pug: -------------------------------------------------------------------------------- 1 | h1 TEST0 PAGE 2 | a(href="") 哈哈哈哈哈 3 | -------------------------------------------------------------------------------- /app/static/js/test/index.js: -------------------------------------------------------------------------------- 1 | import '../../css/index.css' 2 | console.log( 'test' ); 3 | -------------------------------------------------------------------------------- /app/templates/test/css/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #000; 3 | color: #fff; 4 | } 5 | -------------------------------------------------------------------------------- /app/templates/test0/index.js: -------------------------------------------------------------------------------- 1 | import './css/index.css' 2 | console.log('aaaaaaaaaaaa') 3 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"], 3 | "plugins": ["transform-es2015-spread", "istanbul"] 4 | } -------------------------------------------------------------------------------- /app/static/img/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CavinHuang/webpack-multi-skeleton/HEAD/app/static/img/1.jpg -------------------------------------------------------------------------------- /app/templates/test0/css/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #000; 3 | color: #fff; 4 | } 5 | h1 { 6 | color: red; 7 | } 8 | -------------------------------------------------------------------------------- /app/libs/utils.js: -------------------------------------------------------------------------------- 1 | export const add = ( num1, num2 ) => { 2 | if ( num1 === undefined ) num1 = 0; 3 | if ( num2 === undefined ) num2 = 0; 4 | return num1 + num2; 5 | } -------------------------------------------------------------------------------- /test/mocks/demo.js: -------------------------------------------------------------------------------- 1 | import Mock from 'mockjs'; 2 | var template = { 3 | 'title': 'Demo01', 4 | 'btnName|1-3': '*' 5 | } 6 | export default Mock.mock(template); -------------------------------------------------------------------------------- /app/templates/test/index.js: -------------------------------------------------------------------------------- 1 | import './css/index.css' 2 | import { 3 | add 4 | } from 'libs/utils' 5 | console.log( add ) 6 | console.log( add( 1 + 2 ) ) 7 | console.log( 'aaaaaaaaaaaa' ) -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: { 4 | browsers: [ 'last 5 version', 'Android >= 4.0' ], 5 | //是否美化属性值 默认:true 6 | cascade: true, 7 | //是否去掉不必要的前缀 默认:true 8 | remove: true, 9 | }, 10 | }, 11 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: stable 3 | 4 | # S: Build Lifecycle 5 | install: 6 | - npm install 7 | 8 | #before_script: 9 | # - npm install -g gulp 10 | 11 | script: 12 | - npm run build 13 | branches: 14 | only: 15 | - master 16 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | // 获取环境命令,并去除首尾空格 2 | process.env.NODE_ENV = process.env.NODE_ENV ? process.env.NODE_ENV : 'product' 3 | const env = process.env.NODE_ENV.replace( /(\s*$)|(^\s*)/ig, '' ) 4 | // 根据环境变量引用相关的配置文件 5 | module.exports = require( `./config/webpack.config.${env}.js` ) -------------------------------------------------------------------------------- /app/libs/common.js: -------------------------------------------------------------------------------- 1 | console.log( 'lib' ) 2 | import { 3 | add 4 | } from './utils' 5 | export function init() { 6 | let btn = document.createElement( 'button' ) 7 | btn.className = 'btn' 8 | btn.innerHTML = add( 1, 2, 3 ) 9 | document.querySelectorAll( 'body' )[ 0 ].appendChild( btn ) 10 | } -------------------------------------------------------------------------------- /config/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 配置文件 3 | * @type {[type]} 4 | */ 5 | module.exports = { 6 | cssPublicPath: "../static", 7 | imgOutputPath: "img/", // 图片 8 | cssOutputPath: "./static/css/styles.css", // bulid 后的css路径 9 | devServerOutputPath: "../dist", // build后的目录 10 | tplLang: 'pug', // 模板语法,暂时只支持html、pug 11 | libraryDir: 'libs', 12 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://github.com/jiangtao/mydotfiles/blob/master/.config/.editorconfig 2 | root = true 3 | 4 | [*] 5 | 6 | # We recommend you to keep these unchanged 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = false 10 | insert_final_newline = true 11 | [*.{js,php,py}] 12 | 13 | # Change these settings to your own preference 14 | indent_style = space 15 | indent_size = 2 16 | 17 | 18 | [*.md] 19 | insert_final_newline = false 20 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "commonjs": true, 5 | "es6": true, 6 | "node": true 7 | }, 8 | "extends": "eslint:recommended", 9 | "parserOptions": { 10 | "ecmaFeatures": { 11 | "jsx": true 12 | }, 13 | "sourceType": "module" 14 | }, 15 | "rules": { 16 | 'no-console': 'off', 17 | "indent": [ 18 | "error", 19 | "tab" 20 | ], 21 | "linebreak-style": [ 22 | "off", 23 | "windows" 24 | ], 25 | "quotes": [ 26 | "error", 27 | "single" 28 | ], 29 | "semi": [ 30 | "error", 31 | "never" 32 | ] 33 | } 34 | }; -------------------------------------------------------------------------------- /config/webpack.config.product.js: -------------------------------------------------------------------------------- 1 | /** 2 | * build配置 3 | * @type {[type]} 4 | */ 5 | // 引入基础配置 6 | const webpackBase = require( "./webpack.config.base" ); 7 | // 引入 webpack-merge 插件 8 | const webpackMerge = require( "webpack-merge" ); 9 | // 引入 webpack 10 | const webpack = require( "webpack" ); 11 | // 合并配置文件 12 | module.exports = webpackMerge( webpackBase, { 13 | plugins: [ 14 | // 代码压缩 15 | new webpack.optimize.UglifyJsPlugin( { 16 | // 开启 sourceMap 17 | sourceMap: true 18 | } ), 19 | // 提取公共 JavaScript 代码 20 | new webpack.optimize.CommonsChunkPlugin( { 21 | // chunk 名为 commons 22 | name: "commons", 23 | filename: "[name].bundle.js", 24 | } ), 25 | ] 26 | } ); -------------------------------------------------------------------------------- /config/webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 开发环境配置文件 3 | * @type {[type]} 4 | */ 5 | // 引入基础配置文件 6 | const webpackBase = require( "./webpack.config.base" ); 7 | // 引入 webpack-merge 插件 8 | const webpackMerge = require( "webpack-merge" ); 9 | // 引入配置文件 10 | const config = require( "./config" ); 11 | // 合并配置文件 12 | module.exports = webpackMerge( webpackBase, { 13 | // 配置 webpack-dev-server 14 | devServer: { 15 | proxy: { 16 | '/api': { 17 | target: 'http://jsonplaceholder.typicode.com', 18 | changeOrigin: true, 19 | pathRewrite: { 20 | '^/api': '' 21 | } 22 | } 23 | }, 24 | // 项目根目录 25 | contentBase: config.devServerOutputPath, 26 | // 错误、警告展示设置 27 | overlay: { 28 | errors: true, 29 | warnings: true 30 | } 31 | } 32 | } ); -------------------------------------------------------------------------------- /config/webpack.config.lint.js: -------------------------------------------------------------------------------- 1 | /** 2 | * eslint 配置 3 | * @type {[type]} 4 | */ 5 | const webpackBase = require( "./webpack.config.base" ); 6 | const webpackMerge = require( "webpack-merge" ); 7 | const config = require( "./config" ); 8 | module.exports = webpackMerge( webpackBase, { 9 | module: { 10 | rules: [ 11 | { 12 | test: /\.js$/, 13 | // 强制先进行 ESLint 检查 14 | enforce: "pre", 15 | // node_modules 和 lib 文件夹中的代码不进行检查 16 | exclude: /node_modules|lib/, 17 | loader: "eslint-loader", 18 | options: { 19 | // 启用自动修复 20 | fix: true, 21 | // 启用警告信息 22 | emitWarning: true, 23 | } 24 | }, 25 | ] 26 | }, 27 | devServer: { 28 | contentBase: config.devServerOutputPath, 29 | overlay: { 30 | errors: true, 31 | warnings: true 32 | } 33 | } 34 | } ); -------------------------------------------------------------------------------- /test/unit/demo.spec.js: -------------------------------------------------------------------------------- 1 | import add from '../../app/libs/utils'; 2 | import { 3 | expect 4 | } from "chai"; 5 | describe( '第一个测试套件', function () { 6 | it( '第一个测试用例: 1+1 === 2', function () { 7 | expect( 1 + 1 ) 8 | .to.be.equal( 2 ); 9 | } ); 10 | it( '第二个测试用例: 1+1 === 2', function () { 11 | expect( 1 + 1 ) 12 | .to.be.equal( 2 ); 13 | } ); 14 | } ); 15 | 16 | describe( '第二个测试套件', function () { 17 | it( '第一个测试用例: 1+1 === 2', function () { 18 | expect( add( 1, 1 ) ) 19 | .to.be.equal( 2 ); 20 | } ); 21 | it( '第二个测试用例: 1+1 === 2', function () { 22 | expect( add() ) 23 | .to.be.equal( 0 ); 24 | } ); 25 | it( '第二个测试用例: 1+1 === 2', function () { 26 | expect( add( 1 ) ) 27 | .to.be.equal( 1 ); 28 | } ); 29 | it( '第二个测试用例: 1+1 === 2', function () { 30 | expect( add( undefined, 1 ) ) 31 | .to.be.equal( 2 ); 32 | } ); 33 | } ); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack-multi-skeleton", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "set NODE_ENV=dev && webpack-dev-server --open --progress --color", 8 | "build": "set NODE_ENV=product && webpack -p --progress --color", 9 | "lint": "set NODE_ENV=lint && webpack-dev-server --open", 10 | "lint2": "./node_modules/.bin/eslint *.js", 11 | "start": "http-server ./dist -p 8888 -o", 12 | "start2": "http-server ./dist -p 8888", 13 | "test-unit": "karma start", 14 | "test-e2e": "./node_modules/.bin/nightwatch --config \"./test/e2e/runner.js\" --env chrome" 15 | }, 16 | "author": "", 17 | "license": "MIT", 18 | "devDependencies": { 19 | "autoprefixer": "^7.2.3", 20 | "babel-core": "^6.26.0", 21 | "babel-eslint": "^8.2.1", 22 | "babel-loader": "^7.1.2", 23 | "babel-plugin-istanbul": "^4.1.5", 24 | "babel-plugin-transform-runtime": "^6.23.0", 25 | "babel-preset-env": "^1.6.1", 26 | "babel-preset-es2015": "^6.24.1", 27 | "chai": "^4.1.2", 28 | "clean-webpack-plugin": "^0.1.17", 29 | "css-loader": "^0.28.7", 30 | "eslint": "^4.15.0", 31 | "eslint-config-airbnb-base": "^12.1.0", 32 | "eslint-plugin-html": "^4.0.1", 33 | "eslint-plugin-import": "^2.8.0", 34 | "eslint-plugin-standard": "^3.0.1", 35 | "extract-text-webpack-plugin": "^3.0.2", 36 | "file-loader": "^1.1.5", 37 | "html-loader": "^0.5.1", 38 | "html-webpack-plugin": "^2.30.1", 39 | "html-withimg-loader": "^0.1.16", 40 | "istanbul-instrumenter-loader": "^3.0.0", 41 | "jasmine": "^2.9.0", 42 | "jasmine-core": "^2.9.1", 43 | "karma": "^2.0.0", 44 | "karma-chai": "^0.1.0", 45 | "karma-chrome-launcher": "^2.2.0", 46 | "karma-coverage": "^1.1.1", 47 | "karma-coverage-istanbul-reporter": "^1.4.1", 48 | "karma-jasmine": "^1.1.1", 49 | "karma-mocha": "^1.3.0", 50 | "karma-sourcemap-loader": "^0.3.7", 51 | "karma-spec-reporter": "^0.0.32", 52 | "karma-webpack": "^2.0.9", 53 | "mocha": "^5.0.0", 54 | "mock": "^0.1.1", 55 | "mockjs": "^1.0.1-beta3", 56 | "postcss-loader": "^2.0.9", 57 | "pug-html-loader": "^1.1.5", 58 | "style-loader": "^0.19.0", 59 | "stylus": "^0.54.5", 60 | "stylus-loader": "^3.0.1", 61 | "url-loader": "^0.6.2", 62 | "webpack": "^3.10.0", 63 | "webpack-dev-server": "^2.9.7", 64 | "webpack-merge": "^4.1.1" 65 | }, 66 | "dependencies": { 67 | "eslint-loader": "^1.9.0" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Generated on Sat Aug 26 2017 20:31:19 GMT+0800 (中国标准时间) 3 | 4 | module.exports = function ( config ) { 5 | config.set( { 6 | // 将用于解析所有模式的基本路径(例如,文件,排除)ps: 修改它会影响files和exclude路径,没有特殊需求默认就行。 7 | basePath: '', 8 | // 选择测试框架我们选的‘jasmine’ 可以在这里去找更多相关的框架 https://npmjs.org/browse/keyword/karma-adapter 9 | frameworks: [ 'jasmine', 'mocha' ], 10 | // 在浏览器中加载的匹配的文件列表 就是我们的第4步 11 | files: [ 'test/**/*.spec.js' ], 12 | // 要排除的文件列表 就是我们的第5步 13 | exclude: [], 14 | // 在将其提供给浏览器之前,预处理匹配的文件, 可用的预处理器 https://npmjs.org/browse/keyword/karma-preprocessor 15 | // 测试文件需要处理一下,各框架和库都不一样,可以在链接中找到你对应的框架的处理器 16 | // key是文件夹路径,也是就files的路径,value是一个数组,也就是预处理器集合 17 | preprocessors: { 18 | 'test/**/*.spec.js': [ 'webpack', 'sourcemap' ] 19 | }, 20 | // webpack配置 不需要入口(entry)和输出(output)配置 21 | webpack: { 22 | devtool: 'inline-source-map', 23 | module: { 24 | rules: [ { 25 | test: /\.js$/, 26 | use: { 27 | loader: 'istanbul-instrumenter-loader', 28 | options: { 29 | esModules: true 30 | } 31 | }, 32 | enforce: 'pre', 33 | exclude: /node_modules|\.spec\.js$/, 34 | }, { 35 | test: /\.js$/, 36 | use: { 37 | loader: 'babel-loader', 38 | options: { 39 | presets: [ 'es2015' ], 40 | plugins: [ 'istanbul' ] 41 | } 42 | }, 43 | exclude: /node_modules/ 44 | } ] 45 | } 46 | }, 47 | webpackMiddleware: { 48 | noInfo: true 49 | }, 50 | // 依赖插件 51 | plugins: [ 52 | 'karma-chrome-launcher', 53 | 'karma-jasmine', 54 | 'karma-mocha', 55 | 'karma-webpack', 56 | 'karma-sourcemap-loader', 57 | 'karma-coverage-istanbul-reporter' 58 | ], 59 | // 怎么显示测试结果 测试结果显示插件https://npmjs.org/browse/keyword/karma-reporter 60 | reporters: [ 'coverage-istanbul' ], 61 | // 配置覆盖率报告的查看方式配置 62 | coverageIstanbulReporter: { 63 | // 可以用什么形式展示 支持以下格式:clover、cobertura、html、json-summary、json、lcov、lcovonly、none、teamcity、text-lcov、text-summary、text 64 | // 可以看连接 : https://github.com/istanbuljs/istanbul-reports/tree/590e6b0089f67b723a1fdf57bc7ccc080ff189d7/lib 65 | reports: [ 'html', 'text-summary' ], 66 | // 结果存放的位置 67 | dir: 'coverage/', 68 | // 如果使用webpack和预加载器,可以绕过webpack打破源路径 69 | fixWebpackSourcePaths: true, 70 | // 停止输出消息,如`File [$ {filename}]忽略,没有任何东西可以映射 71 | skipFilesWithNoCoverage: true, 72 | // 大多数记录接受额外的配置选项。 你可以通过`report-config`选项传递这些 73 | 'report-config': { 74 | // 配置html 75 | html: { 76 | // 输出到 ./coverage/html 77 | subdir: 'html' 78 | } 79 | } 80 | }, 81 | // 运行的服务端口,可以自己修改 82 | port: 9876, 83 | // 在输出中启用/禁用颜色(记录(reporters)和日志(logs)) 肯定需要看到运行的结果,不然出错了也不好调试 84 | colors: true, 85 | // 显示日志记录的级别 (默认就好) 86 | // 可能的值: config.LOG_DISABLE (禁用) || config.LOG_ERROR (错误) || config.LOG_WARN (警告)|| config.LOG_INFO (信息)|| config.LOG_DEBUG (调试) 87 | logLevel: config.LOG_INFO, 88 | // 每当任何测试文件更改时,启用/禁用监听文件并执行测试 这就是第6步 89 | autoWatch: true, 90 | // 可以启动的浏览器列表 需要去下载对应的启动插件 https://npmjs.org/browse/keyword/karma-launcher 91 | browsers: [ 'Chrome' ], 92 | // 持续集成模式 如果是,Karma启动浏览器,运行测试并退出 默认就好,设true你会后悔的。 93 | singleRun: false, 94 | // 并发级别 可以同时启动多少浏览器 默认无限大 95 | concurrency: Infinity 96 | } ) 97 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # webpack 多页面骨架 2 | ![building](https://www.travis-ci.org/CavinHuang/webpack-multi-skeleton.svg?branch=master "build status") 3 | --- 4 | >config目录下都是webpack相关配置 5 | 包含开发环境配置、打包配置、jsLint配置 6 | 7 | ## Build Setup 8 | 9 | ``` bash 10 | # install dependencies 11 | $ npm install # Or yarn install*[see note below] 12 | 13 | # serve with hot reload at localhost:3000 14 | $ npm run dev 15 | 16 | # build for production and launch server 17 | $ npm run build 18 | $ npm start 19 | 20 | ``` 21 | ## 更新(18/2/7) 22 | - 添加文件夹别名,方便引入 23 | - @ 代表项目根目录 24 | - app 代表 app目录 25 | - libs 代表app/libs目录 26 | - static 代表app/static目录 27 | - templates 代表app/templates目录 28 | - 添加eslint方便代码统一 29 | - 添加单元测试模块,方便开发测试 30 | 31 | ## 更新(18/1/20) 32 | - 添加output模块化 33 | - 支持一个模块多个模板文件(即html文件夹支持放多个文件了,一样可以自动加载) 34 | 35 | ## 更新(18/1/17) 36 | - 去除原先手动添加第三方库入口,改为自动注入 37 | 38 | ## 更新(18/1/11) 39 | - 去除原先的手动添加模块的配置 40 | - 添加自动注入模块 41 | - 调整目录结构 42 | - static 调整为公共静态资源 43 | - libs 调整为第三方插件静态资源 44 | 45 | ---- 46 | ## 完整的目录结构如下: 47 | ``` 48 | ├─app 49 | │ ├─libs 50 | │ │ common.js 51 | │ │ test.css 52 | │ │ 53 | │ ├─static 54 | │ │ ├─css 55 | │ │ ├─img 56 | │ │ │ 1.jpg 57 | │ │ │ 58 | │ │ └─js 59 | │ │ └─test 60 | │ │ index.js 61 | │ │ 62 | │ └─templates 63 | │ ├─test 64 | │ │ │ index.js 65 | │ │ │ 66 | │ │ ├─css 67 | │ │ │ index.css 68 | │ │ │ 69 | │ │ └─html 70 | │ │ index.pug 71 | │ │ 72 | │ └─test0 73 | │ │ index.js 74 | │ │ 75 | │ ├─css 76 | │ │ index.css 77 | │ │ 78 | │ └─html 79 | │ index.pug 80 | │ 81 | ├─config 82 | │ config.js 83 | │ webpack.config.base.js 84 | │ webpack.config.dev.js 85 | │ webpack.config.lint.js 86 | │ webpack.config.prod.js 87 | │ 88 | ├─ .babelrc 89 | ├─ .eslintrc.js 90 | ├─ .gitignore 91 | ├─ .travis.yml 92 | ├─ package-lock.json 93 | ├─ package.json 94 | ├─ postcss.config.js 95 | ├─ README.md 96 | ├─ webpack.config.js 97 | ├─ yarn.lock 98 | ``` 99 | 100 | ## 打包后的目录结构如下: 101 | ``` 102 | ├─app 103 | │ ├─libs 104 | │ │ common.js 105 | │ │ test.css 106 | │ │ 107 | │ ├─static 108 | │ │ ├─css 109 | │ │ ├─img 110 | │ │ │ 1.jpg 111 | │ │ │ 112 | │ │ └─js 113 | │ │ └─test 114 | │ │ index.js 115 | │ │ 116 | │ └─templates 117 | │ ├─test 118 | │ │ │ index.js 119 | │ │ │ 120 | │ │ ├─css 121 | │ │ │ index.css 122 | │ │ │ 123 | │ │ └─html 124 | │ │ index.pug 125 | │ │ 126 | │ └─test0 127 | │ │ index.js 128 | │ │ 129 | │ ├─css 130 | │ │ index.css 131 | │ │ 132 | │ └─html 133 | │ index.pug 134 | │ 135 | ├─config 136 | │ config.js 137 | │ webpack.config.base.js 138 | │ webpack.config.dev.js 139 | │ webpack.config.lint.js 140 | │ webpack.config.prod.js 141 | │ 142 | ├─dist 143 | │ │ commons.bundle.js 144 | │ │ test.html 145 | │ │ test0.html 146 | │ │ vendor.bundle.js 147 | │ │ 148 | │ └─static 149 | │ ├─css 150 | │ │ 04e50154927e0a6be02a227c0d77b994.css 151 | │ │ 08d7b51b4ab4894412d8e4d36eb9632c.css 152 | │ │ c38343268b141a3cde95bccc552e4376.css 153 | │ │ 154 | │ └─js 155 | │ └─templates 156 | │ test.bundle.dd711e4715e98405c3fb.js 157 | │ test0.bundle.dd711e4715e98405c3fb.js 158 | │ 159 | ├─.babelrc 160 | ├─.eslintrc.js 161 | ├─.gitignore 162 | ├─.travis.yml 163 | ├─list.txt 164 | ├─package-lock.json 165 | ├─package.json 166 | ├─postcss.config.js 167 | ├─README.md 168 | ├─webpack.config.js 169 | ├─yarn.lock 170 | │ 171 | ``` 172 | -------------------------------------------------------------------------------- /config/webpack.config.base.js: -------------------------------------------------------------------------------- 1 | /** 2 | * webpack 基础配置 3 | * @type {[type]} 4 | */ 5 | const path = require( "path" ); 6 | const webpack = require( 'webpack' ); 7 | const glob = require( "glob" ) 8 | // 引入插件 9 | const HTMLWebpackPlugin = require( "html-webpack-plugin" ); 10 | // 清理 dist 文件夹 11 | const CleanWebpackPlugin = require( "clean-webpack-plugin" ) 12 | // 抽取 css 13 | const ExtractTextPlugin = require( "extract-text-webpack-plugin" ); 14 | // 引入配置 15 | const config = require( "./config" ); 16 | // 通过 html-webpack-plugin 生成的 HTML 集合 17 | let HTMLPlugins = []; 18 | // 入口文件集合 19 | let Entries = {} 20 | 21 | function getEntryDir() { 22 | let globPath = 'app/templates/**/*.' + config.tplLang 23 | // (\/|\\\\) 这种写法是为了兼容 windows和 mac系统目录路径的不同写法 24 | let pathDir = 'app(\/|\\\\)(.*?)(\/|\\\\)html' 25 | let files = glob.sync( globPath ) 26 | let dirname, entries = [] 27 | for ( let i = 0; i < files.length; i++ ) { 28 | dirname = path.dirname( files[ i ] ) 29 | entries.push( { 30 | html: files[ i ], 31 | dir: dirname.replace( new RegExp( '^' + pathDir ), '$2' ) 32 | } ) 33 | } 34 | return entries; 35 | } 36 | // 生成多页面的集合 37 | getEntryDir() 38 | .forEach( ( page ) => { 39 | let moduleName = page.dir.split( '/' ) 40 | let pathArr = page.html.split( '/' ) 41 | let fileName = pathArr[ pathArr.length - 1 ].split( '.' )[ 0 ] 42 | let moduleNameStr = moduleName[ moduleName.length - 1 ] 43 | const htmlPlugin = new HTMLWebpackPlugin( { 44 | filename: `${moduleNameStr}/${fileName}.html`, 45 | template: path.resolve( __dirname, `../${page.html}` ), 46 | chunks: [ moduleNameStr, 'vendors' ], 47 | } ); 48 | HTMLPlugins.push( htmlPlugin ); 49 | Entries[ moduleNameStr ] = path.resolve( __dirname, `../app/${page.dir}/index.js` ); 50 | } ) 51 | 52 | function getVendors() { 53 | let globPath = `app/${config.libraryDir}/**/*.*` 54 | let files = glob.sync( globPath ) 55 | let libsArr = [] 56 | files.forEach( ( v, i ) => { 57 | libsArr.push( './' + v ) 58 | } ) 59 | return libsArr 60 | } 61 | let vendorsDir = getVendors() 62 | if ( vendorsDir.length > 0 ) Entries[ 'vendors' ] = vendorsDir // 第三方类库 63 | let webpackconfig = { 64 | entry: Entries, 65 | devtool: "cheap-module-source-map", 66 | output: { 67 | filename: "static/js/[name].bundle.[hash].js", 68 | path: path.resolve( __dirname, config.devServerOutputPath ) 69 | }, 70 | // 加载器 71 | module: { 72 | rules: [ { 73 | test: /\.css$/, 74 | exclude: /node_modules/, 75 | use: ExtractTextPlugin.extract( { 76 | fallback: "style-loader", 77 | publicPath: config.cssPublicPath, 78 | use: [ { 79 | loader: "css-loader", 80 | options: { 81 | minimize: true, // 开启 css 压缩 82 | } 83 | }, { 84 | loader: "postcss-loader" 85 | } ] 86 | } ) 87 | }, { 88 | test: /\.styl(us)?$/, 89 | use: [ 'style-loader', 'css-loader', { 90 | loader: "postcss-loader", 91 | options: { 92 | plugins: function () { 93 | return [ require( 'autoprefixer' ) ]; 94 | } 95 | } 96 | }, 'stylus-loader' ] 97 | }, { 98 | test: /\.pug$/, 99 | loader: [ 'html-loader', 'pug-html-loader' ] 100 | }, { 101 | test: /\.js$/, 102 | exclude: /node_modules/, 103 | use: { 104 | loader: 'babel-loader', 105 | options: { 106 | presets: [ 'es2015' ] 107 | } 108 | } 109 | }, { 110 | test: /\.(png|svg|jpg|gif)$/, 111 | use: { 112 | loader: "file-loader", 113 | options: { 114 | // 打包生成图片的名字 115 | name: "[name].[ext]", 116 | // 图片的生成路径 117 | outputPath: config.imgOutputPath 118 | } 119 | } 120 | }, { 121 | test: /\.(woff|woff2|eot|ttf|otf)$/, 122 | use: [ "file-loader" ] 123 | }, { 124 | test: /\.(htm|html)$/i, 125 | loader: 'html-withimg-loader' 126 | } ], 127 | }, 128 | devtool: 'eval', 129 | plugins: [ 130 | new webpack.optimize.CommonsChunkPlugin( { 131 | name: 'vendors', 132 | filename: 'vendor.bundle.js' 133 | } ), 134 | new webpack.DefinePlugin( { 135 | 'process.env': { 136 | NODE_ENV: JSON.stringify( process.env.NODE_ENV ) 137 | } 138 | } ), 139 | // 自动清理 dist 文件夹 140 | new CleanWebpackPlugin( [ config.devServerOutputPath ] ), 141 | // 将 css 抽取到某个文件夹 142 | new ExtractTextPlugin( { 143 | //生成css文件名 144 | filename: 'static/css/[name].[contenthash].css', 145 | disable: false, 146 | allChunks: true 147 | } ), 148 | new webpack.NoEmitOnErrorsPlugin(), 149 | new webpack.HashedModuleIdsPlugin(), 150 | // 自动生成 HTML 插件 151 | ...HTMLPlugins 152 | ], 153 | resolve: { 154 | extensions: [ '.js', '.css', '.styl' ], 155 | alias: { 156 | "@": path.join( __dirname, "../" ), 157 | "app": path.join( __dirname, "../app" ), 158 | "libs": path.join( __dirname, "../app/libs" ), 159 | "static": path.join( __dirname, "../app/static" ), 160 | "templates": path.join( __dirname, "../app/templates" ), 161 | } 162 | } 163 | } 164 | module.exports = webpackconfig --------------------------------------------------------------------------------