diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index fa6f49039a4a..b5d199815e2c 100755 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,4 +1,6 @@ - [ ] Check the current issues to ensure you aren't creating a duplicate. - [ ] Consider making small typo fixes and such directly as pull requests. +- [ ] For the voting application, go to https://github.com/webpack-contrib/voting-app. +- [ ] For loader/plugin docs, consider opening an issue in the corresponding repository. - [ ] No existing issue? Go ahead and open a new one. - __Remove these instructions from your PR as they are for your eyes only.__ diff --git a/README.md b/README.md index a7cc545215d3..cdc73866bb6a 100755 --- a/README.md +++ b/README.md @@ -44,37 +44,37 @@ npm start # webpack.js.org -[![build status](https://secure.travis-ci.org/webpack/webpack.js.org.svg)](http://travis-ci.org/webpack/webpack.js.org) -[![Standard Version](https://img.shields.io/badge/release-standard%20version-brightgreen.svg)](https://github.com/conventional-changelog/standard-version) +[![Build Status][13]][10] +[![Standard Version][12]][11] Guides, documentation, and all things webpack. ## Content Progress -Now that we've covered much of the backlog of _missing documentation_, we are starting -to heavily review each section of the site's content to sort and structure it appropriately. -The following issues should provide a pretty good idea of where things are, and where -they are going: +Now that we've covered much of the backlog of _missing documentation_, we are +starting to heavily review each section of the site's content to sort and +structure it appropriately. The following issues should provide a pretty good +idea of where things are, and where they are going: - [Guides - Review and Simplify][1] -- [Concepts - Review, Organize, Define Clear Goals][2] +- [Concepts - Review and Organize][2] +- [API - v4 Rewrite][8] -We haven't created issues for the other sections yet, but they will be coming soon. For -dev-related work please see [General - Current Longterm Plan][3], which will soon be -replaced by a more dev-specific issue. +We haven't created issues for the other sections yet, but they will be coming +soon. For dev-related work please see [General - Updates & Fixes][3]. ## Translation -If you hope to localize this documentation please jump to the [translate branch][4]. +To help translate this documentation please jump to the [translate branch][4]. ## Contributing -Read through the [writer's guide][7] if you're interested in editing the content on this -site. See the [contributors page][5] to learn how to set up and start working on the site -locally. +Read through the [writer's guide][7] if you're interested in editing the +content on this site. See the [contributors page][5] to learn how to set up and +start working on the site locally. ## License @@ -82,10 +82,24 @@ locally. The content is available under the [Creative Commons BY 4.0][6] license. +## Special Thanks + +_BrowserStack_ has graciously allowed us to do cross-browser and cross-os +testing of the site at no cost... + +[![BrowserStackLogo](./browserstack-logo.png)][9] + + [1]: https://github.com/webpack/webpack.js.org/issues/1258 [2]: https://github.com/webpack/webpack.js.org/issues/1386 -[3]: https://github.com/webpack/webpack.js.org/issues/1380 +[3]: https://github.com/webpack/webpack.js.org/issues/1525 [4]: https://github.com/webpack/webpack.js.org/tree/translation [5]: https://github.com/webpack/webpack.js.org/blob/master/.github/CONTRIBUTING.md [6]: https://creativecommons.org/licenses/by/4.0/ [7]: https://webpack.js.org/writers-guide +[8]: https://github.com/webpack/webpack.js.org/pull/1754 +[9]: http://browserstack.com/ +[10]: http://travis-ci.org/webpack/webpack.js.org +[11]: https://github.com/conventional-changelog/standard-version +[12]: https://img.shields.io/badge/release-standard%20version-brightgreen.svg +[13]: https://secure.travis-ci.org/webpack/webpack.js.org.svg diff --git a/UPDATE.md b/UPDATE.md new file mode 100644 index 000000000000..14b8bbb3fc7c --- /dev/null +++ b/UPDATE.md @@ -0,0 +1,5 @@ +## 更新记录 + +### 2018.01.13 +* 合并记录:合并 master 分支 +* 合并记录:https://github.com/webpack-china/webpack.js.org/pull/433 diff --git a/browserstack-logo.png b/browserstack-logo.png new file mode 100644 index 000000000000..f1deff83be7e Binary files /dev/null and b/browserstack-logo.png differ diff --git a/package.json b/package.json index a8462a6d5dc3..b9ad10f47042 100755 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "antwar-helpers": "^0.19.0", "antwar-interactive": "^0.19.0", "async": "^2.5.0", - "autoprefixer": "^7.1.3", + "autoprefixer": "^7.2.3", "babel-core": "^6.26.0", "babel-eslint": "^7.2.3", "babel-loader": "^7.1.2", @@ -55,12 +55,12 @@ "babel-plugin-transform-object-rest-spread": "^6.26.0", "babel-preset-env": "^1.6.0", "babel-preset-react": "^6.24.1", - "copy-webpack-plugin": "^4.0.1", + "copy-webpack-plugin": "^4.3.0", "css-loader": "^0.28.5", "duplexer": "^0.1.1", "eslint": "4.5.0", "eslint-loader": "^1.9.0", - "eslint-plugin-markdown": "^1.0.0-beta.6", + "eslint-plugin-markdown": "^1.0.0-beta.7", "extract-text-webpack-plugin": "^3.0.0", "file-loader": "^0.11.2", "fontgen-loader": "^0.2.1", @@ -69,22 +69,22 @@ "github": "^10.0.0", "html-webpack-plugin": "^2.30.1", "http-server": "^0.10.0", - "hyperlink": "^3.0.0", + "hyperlink": "^3.0.1", "loader-utils": "^1.1.0", "lodash": "^4.17.4", "markdown-loader": "^2.0.1", "markdownlint": "^0.6.0", "markdownlint-cli": "^0.3.1", - "marked": "^0.3.6", + "marked": "^0.3.7", "mkdirp": "^0.5.1", "modularscale-sass": "^3.0.3", - "moment": "^2.18.1", + "moment": "^2.20.1", "ncp": "^2.0.0", "node-sass": "^4.5.3", "npm-run-all": "^4.1.1", "postcss-loader": "^2.0.6", "prism-languages": "^0.3.3", - "prismjs": "^1.6.0", + "prismjs": "^1.9.0", "raw-loader": "^0.5.1", "request": "^2.81.0", "sass-loader": "^6.0.6", @@ -94,14 +94,14 @@ "tap-parser": "^6.0.1", "through2": "^2.0.3", "url-loader": "^0.5.9", - "webpack": "^3.5.5", - "webpack-dev-server": "^2.7.1", + "webpack": "^3.10.0", + "webpack-dev-server": "^2.9.7", "webpack-merge": "^4.1.0", "yaml-frontmatter-loader": "^0.1.0" }, "dependencies": { - "ajv": "^5.2.2", - "preact": "^8.2.5", + "ajv": "^5.5.2", + "preact": "^8.2.7", "preact-compat": "3.17.0", "prop-types": "^15.5.10", "react": "^15.6.1", @@ -109,6 +109,7 @@ "react-router": "^4.2.0", "react-router-dom": "^4.2.2", "tool-list": "^0.11.0", + "webpack.vote": "^0.1.2", "whatwg-fetch": "^2.0.3" } } diff --git a/src/assets/homepage-modules.svg b/src/assets/homepage-modules.svg deleted file mode 100755 index a39441644b53..000000000000 --- a/src/assets/homepage-modules.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/components/Navigation/Links.json b/src/components/Navigation/Links.json index c46d5a0080c5..d7ec12ee950b 100644 --- a/src/components/Navigation/Links.json +++ b/src/components/Navigation/Links.json @@ -15,6 +15,10 @@ "title": "参与贡献", "url": "contribute" }, + { + "title": "投票", + "url": "vote" + }, { "title": "博客", "url": "//medium.com/webpack" diff --git a/src/components/NotificationBar/NotificationBar.jsx b/src/components/NotificationBar/NotificationBar.jsx index 41deb5c66aed..50a2faee4e9d 100755 --- a/src/components/NotificationBar/NotificationBar.jsx +++ b/src/components/NotificationBar/NotificationBar.jsx @@ -2,7 +2,7 @@ import React from 'react'; import Container from '../Container/Container'; import testLocalStorage from '../../utilities/test-local-storage'; -const version = '1'; +const version = '2'; const localStorageIsEnabled = testLocalStorage() !== false; export default class NotificationBar extends React.Component { @@ -13,17 +13,16 @@ export default class NotificationBar extends React.Component {
- 赞助 webpack,同时获取官方衣服!访问 webpack 官方商店! 查看所有收益请转到 webpack 的 Open Collective 页面! -
-- 在 Unixstickers! 上购买全新的 webpack 贴纸 - {localStorageIsEnabled ? - : - null - } + 赞助 webpack,同时从官方商店购买衣服{' '} + 或者在这里购买贴纸!所有收益将转到我们的{' '} + open collective!
+ { localStorageIsEnabled ? + : + null + }
下面表格包含一个起步配套工具的辅助列表,
可以作为基于 webpack 的项目的起点。
- 要向列表添加新的配套工具请访问
- 仓库
+ 要向列表添加新的配套工具请访问{' '}
+ 仓库{' '}
以及提交一个 PR 来修改这个文件
generator/starterProjectUrls.js
.
- 模板应该是用于验证概念, + 模板应该是用于验证概念, 以帮助你学习各种框架的 webpack 不同技术。 确保你了解他们在做什么,并避免复制和粘贴制造重复代码。 另外还请注意,这些都不是由 webpack 官方支持的。 diff --git a/src/components/Vote/App.jsx b/src/components/Vote/App.jsx deleted file mode 100755 index cfba8704f200..000000000000 --- a/src/components/Vote/App.jsx +++ /dev/null @@ -1,411 +0,0 @@ -import React from 'react'; -import 'whatwg-fetch'; -import * as api from "./api"; -import VoteButton from './Button/Button'; -import Influence from './Influence'; -import GithubMark from '../../assets/github-logo.svg'; - -function updateByProperty(array, property, propertyValue, update) { - return array.map(item => { - if(item[property] === propertyValue) { - return update(item); - } else { - return item; - } - }); -} - -export default class VoteApp extends React.Component { - constructor(props) { - super(props); - this.state = { - selfInfo: undefined, - listInfo: undefined, - isFetchingSelf: false, - isVoting: 0 - }; - } - - isBrowserSupported() { - return typeof localStorage === 'object'; - } - - componentDidMount() { - if(!this.isBrowserSupported()) - return; - - let { selfInfo, listInfo } = this.state; - - if(api.isLoginActive()) { - this.setState({ - isLoginActive: true - }); - api.continueLogin().then(token => { - window.localStorage.voteAppToken = token; - }); - } else { - if(!selfInfo) { - this.updateSelf(); - } - if(!listInfo) { - this.updateList(); - } - } - } - - componentWillReceiveProps(props) { - if(!this.isBrowserSupported()) - return; - - this.updateList(props); - } - - updateSelf() { - let { voteAppToken } = localStorage; - if(voteAppToken) { - this.setState({ - isFetchingSelf: true - }); - api.getSelf(voteAppToken).catch(e => { - this.setState({ - selfInfo: null, - isFetchingSelf: false - }); - }).then(result => { - this.setState({ - selfInfo: result, - isFetchingSelf: false - }); - }); - } - } - - updateList(props = this.props) { - let { name } = props; - let { voteAppToken } = localStorage; - this.setState({ - isFetchingList: true - }); - api.getList(voteAppToken, name).catch(e => { - this.setState({ - listInfo: null, - isFetchingList: false - }); - }).then(result => { - this.setState({ - listInfo: result, - isFetchingList: false - }); - }); - } - - localVote(itemId, voteName, diffValue, currencyName, score) { - let { selfInfo, listInfo } = this.state; - this.setState({ - isVoting: this.state.isVoting + 1, - listInfo: listInfo && { - ...listInfo, - items: updateByProperty(listInfo.items, "id", itemId, item => ({ - ...item, - votes: updateByProperty(item.votes, "name", voteName, vote => ({ - ...vote, - votes: vote.votes + diffValue - })), - userVotes: updateByProperty(item.userVotes, "name", voteName, vote => ({ - ...vote, - votes: vote.votes + diffValue - })), - score: item.score + score * diffValue - })) - }, - selfInfo: selfInfo && { - ...selfInfo, - currencies: updateByProperty(selfInfo.currencies, "name", currencyName, currency => ({ - ...currency, - used: currency.used + diffValue, - remaining: currency.remaining - diffValue - })) - } - }); - } - - vote(itemId, voteName, diffValue, currencyName, score) { - if(!diffValue) return; - this.localVote(itemId, voteName, diffValue, currencyName, score); - let { voteAppToken } = localStorage; - api.vote(voteAppToken, itemId, voteName, diffValue).catch(e => { - console.error(e); - // revert local vote - this.localVote(itemId, voteName, -diffValue, currencyName, score); - this.setState({ - isVoting: this.state.isVoting - 1 - }); - }).then(() => { - this.setState({ - isVoting: this.state.isVoting - 1 - }); - }); - } - - render() { - let { name } = this.props; - - if(!this.isBrowserSupported()) - returnYour browser is not supported.; - - let { selfInfo, listInfo, isVoting, isFetchingList, isFetchingSelf, isCreating, isLoginActive, editItem, editItemTitle, editItemDescription } = this.state; - - let { voteAppToken } = localStorage; - - if(isLoginActive) { - returnLogging in...; - } - - const inProgress = isFetchingList || isFetchingSelf || isCreating || isVoting; - - let maxVoteInfo = listInfo && listInfo.possibleVotes.map(() => 0); - - if(listInfo) listInfo.items.forEach(item => { - if(item.userVotes) { - maxVoteInfo.forEach((max, idx) => { - let votes = item.userVotes[idx].votes; - if(votes > max) - maxVoteInfo[idx] = votes; - }); - } - }); - return ( --- ); - } - - renderSelf (inProgress) { - let { listInfo, selfInfo, isFetchingSelf } = this.state; - if(!selfInfo) { - if(isFetchingSelf) { - return- Vote ---- { listInfo &&------- - - DISCLAIMER: Since this feature is its Alpha stages, the formula for calculating influence may change. --- {this.renderSelf(inProgress)} ---} -{listInfo.displayName}
-{listInfo.description}-- { listInfo.items.map(item =>
-- -
)} - { listInfo.isAdmin &&---- { editItem !== item.id &&{item.score}- {listInfo.possibleVotes.map((voteSettings, idx) => { - let vote = item.votes[idx]; - let userVote = item.userVotes && item.userVotes[idx]; - let currencyInfo = selfInfo && voteSettings.currency && this.findByName(selfInfo.currencies, voteSettings.currency); - let maximum = voteSettings.maximum || 1000; // infinity - let minimum = voteSettings.minimum || 0; - let value = (userVote && userVote.votes) ? userVote.votes: 0; - if(currencyInfo && currencyInfo.remaining + value < maximum) maximum = currencyInfo.remaining + value; - return-; - })} -{ - this.vote(item.id, voteSettings.name, diffValue, voteSettings.currency, voteSettings.score); - }} - /> - - {item.title} - {item.description} - { listInfo.isAdmin &&} - { editItem === item.id &&- - - - - -} --} -- this.setState({ editItemTitle: e.target.value })} /> ---- -- -
} -this.setState({newTitle: e.target.value})} />- - -Loading user info...; - } - return ; - } else { - return-; - } - } - - findByName(array, name) { - for(var i = 0; i < array.length; i++) - if(array[i].name === name) - return array[i]; - return null; - } - - getNiceVoteValues(maximum) { - var arr = []; - var b = true; - for(var x = 1; x < maximum; x *= b ? 5 : 2, b = !b) { - arr.push(x); - } - if(maximum) - arr.push(maximum); - return arr; - } - - getStep(maximum) { - return Math.floor(maximum / 20) * 2 || 1; - } - - getColor(name) { - switch(name) { - case "influence": return "blue"; - case "golden": return "#bfa203"; - case "thumb": return "#535353"; - } - return undefined; - } -} diff --git a/src/components/Vote/App.scss b/src/components/Vote/App.scss deleted file mode 100755 index bc91ef1c6be1..000000000000 --- a/src/components/Vote/App.scss +++ /dev/null @@ -1,228 +0,0 @@ -@import 'vars'; -@import 'mixins'; -@import 'functions'; - -.vote-app { - margin: 1.5em; - - &__top { - display: flex; - flex-direction: column; - - @include break(medium) { - flex-direction: row; - } - } - - &__influence { - flex: 0 0 75%; - } - - &__influence-description { - display: flex; - flex-direction: column; - - @include break(medium) { - flex-direction: row; - } - } - - &__user-section { - padding: 0 0 30px; - - @include break(medium) { - flex: 0 0 25%; - padding: 0 0 0 20px; - } - - @include break(large) { - border-left: 2px solid getColor(elephant); - } - } - - &__influence-section { - flex: 0 0 50%; - } - - &__influence-disclaimer { - padding: 1em 0; - font-size: smaller; - color: red; - - @include break(medium) { - text-align: center; - } - } - - &__login-button { - margin: 20px 0; - - button { - border: none; - outline: none; - color: getColor(white); - background: getColor(elephant); - padding: 5px 10px 5px 10px; - border-radius: 2px; - font-size: 13px; - cursor: pointer; - - &:hover { - background: black; - } - - &:active { - background: getColor(elephant) - } - } - - img { - height: 25px; - vertical-align: middle; - padding-left: 5px; - } - } - - &__userinfo { - outline: none; - border: none; - background: getColor(elephant); - color: white; - border-radius: 3px; - font-size: 13px; - display: inline-block; - padding: 3px 10px; - - img { - height: 25px; - vertical-align: middle; - margin-right: 10px; - } - } - - &__self-info { - margin-top: 10px; - } - - &__button-area { - margin: 5px 0; - } - - &__update-button { - - } - - h1 { - font-size: 16pt; - font-weight: bold; - margin-bottom: 10px; - } - - &__item-title { - font-size: 16pt; - font-weight: bold; - margin-right: 10px; - } - - &__item-edit-title { - width: 100%; - } - - &__item-edit-description { - width: 100%; - } - - &__currency-list { - display: block; - - & > li { - display: inline-block; - padding: 5px; - } - } - - &__item-card { - display: flex; - flex-direction: column; - margin-top: 30px; - margin-bottom: 30px; - - @include break(medium){ - flex-direction: row; - } - } - - &__score-section { - display: flex; - border: 1px solid lightgray; - user-select: none; - flex-wrap: wrap; - - @include break(medium){ - flex: 0 0 40%; - margin-right: 30px; - padding: 0 0 0 20px; - } - } - - &__item-score { - align-self: center; - font-size: 20pt; - flex: 0 0 100%; - text-align: center; - - @include break(medium){ - flex: 0 0 20%; - text-align: left; - } - } - - &__item-button { - align-self: center; - flex: 0 0 50%; - - @include break(medium){ - flex: 0 0 40%; - } - } - - &__items-list { - display: block; - - & > li { - display: block; - padding: 5px 0; - } - } - - &__currency-influence, &__vote-influence { - color: blue; - &:before { - content: "◆\2009"; - } - } - - &__currency-goldenInfluence, &__vote-golden { - color: #bfa203; - &:before { - content: "◇\2009"; - } - } - - &__currency-support, &__vote-support { - color: green; - &:before { - content: "$\2009"; - } - } - - &__vote-thumb { - - } - - &__admin { - input, textarea, button { - width: 100%; - } - } -} diff --git a/src/components/Vote/Button/Button.jsx b/src/components/Vote/Button/Button.jsx deleted file mode 100755 index 0cff5ba33ec1..000000000000 --- a/src/components/Vote/Button/Button.jsx +++ /dev/null @@ -1,132 +0,0 @@ -import React, {Component} from 'react'; - -export default class NewButton extends Component { - handleClick (n) { - const {maxUp, maxDown, onVote} = this.props; - onVote(Math.min(maxUp, Math.max(n, -maxDown))); - return false; - } - - titleText (n, maxUp, maxDown) { - n = Math.min(maxUp, Math.max(n, -maxDown)); - if(n === 0) - return ""; - return n > 0 ? "+" + n : "" + n; - } - - makeTriangle (n, fn, size, minForEnabled, increase) { - const {maxUp, maxDown, color} = this.props; - const enabled = n !== 0 && (n > 0 ? (maxUp >= minForEnabled) : (maxDown >= minForEnabled)); - const className = "vote-new-button__upDown"; - - if(enabled) { - return this.handleClick(n)} - onMouseDown={() => this.startCounter(increase)} - onMouseUp={() => this.stopCounter()} - onMouseOut={() => this.stopCounter()} - onTouchStart={() => this.startCounter(increase)} - onTouchEnd={() => this.stopCounter()} - onTouchCancel={() => this.stopCounter()} - className={className} - > - {fn({size: size, color: color})} - ; - } else { - return - {fn({size: size, color: "#eee"})} - ; - } - } - - startCounter(increase) { - let current = 0; - let add = 0; - const that = this; - - if (this.interval) { - clearInterval(this.interval); - } - - this.interval = setInterval(function() { - // increase for 1 between 0 and 5 - if(current <= 5) { - current++; - add = 1; - } - // increase for 2 between 6 and 10 - else if(current <= 10) { - current+=2; - add = 2; - } - // increase for 5 between 11 and 40 - else if(current <= 40) { - current+=5; - add = 5; - } - // increase for 10 between 41 and 70 - else if(current <= 70) { - current+=10; - add = 10; - } - // increase for 15 after 71 - else { - current+=15; - add = 15; - } - - if(!increase) { - add *= -1; - } - - that.handleClick(add); - }, 200); - } - - stopCounter() { - if (this.interval) { - clearInterval(this.interval); - } - } - - render() { - const {color, className, value, myValue, canVote} = this.props; - return canVote ? (- - {selfInfo.login} -- { listInfo &&- { selfInfo.currencies - .filter(currency => listInfo.possibleVotes.some(voteSettings => voteSettings.currency === currency.name)) - .map(currency =>
} -- - {currency.remaining} {currency.displayName} -
) } -- - ---): (- {this.makeTriangle(1, triangleUp, 10, 1, true)} - {this.makeTriangle(-1, triangleDown, 10, 1, false)} --- {value} --- ({myValue}) ---); - } -} - -function triangleUp({color, size}) { - let path = `m ${size},0 -${size},${size / 3 * 2} ${size*2},0 z`; - return ; -} - -function triangleDown({color, size}) { - let path = `m ${size},${size / 3 * 2} ${size},-${size / 3 * 2} -${size*2},0 z`; - return ; -} \ No newline at end of file diff --git a/src/components/Vote/Button/Button.scss b/src/components/Vote/Button/Button.scss deleted file mode 100755 index 7a3419a7c8a1..000000000000 --- a/src/components/Vote/Button/Button.scss +++ /dev/null @@ -1,57 +0,0 @@ -@import 'vars'; -@import 'mixins'; -@import 'functions'; - -.vote-button { - text-align: center; - &__value { - font-size: 150%; - } - - &__value, &__my-value, &__upDown { - display: block; - width: 90px; - } - - &__upDown { - border: 0; - padding: 0; - margin: 0; - } -} - -.vote-new-button { - display: flex; - justify-content: center; - - @include break(medium) { - justify-content: inherit; - } - - &__arrows { - flex: 0 0 10%; - } - - &__value { - font-size: 15pt; - } - - &__value, &__my-value{ - display: inline; - margin-left: 5px; - align-self: center; - } - - &__upDown { - border: 0; - padding: 0; - margin: 0; - cursor: pointer; - } - - &__logout-value { - align-self: center; - font-size: 20pt; - margin: auto; - } -} \ No newline at end of file diff --git a/src/components/Vote/Influence.jsx b/src/components/Vote/Influence.jsx deleted file mode 100755 index e2ada69ddfca..000000000000 --- a/src/components/Vote/Influence.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react'; - -export default class InfluenceComponent extends React.Component { - constructor(props) { - super(props); - } - - render() { - return (this.props.type === "normal" ? ( -- {value} --- - ) : ( -Influence
-Influence is a unit of measure based on time you have been a member on GitHub. However, in 2017 and on you will recieve one influence per day.
-- - )); - } -} diff --git a/src/components/Vote/Influence.scss b/src/components/Vote/Influence.scss deleted file mode 100755 index 7e9eba35bc84..000000000000 --- a/src/components/Vote/Influence.scss +++ /dev/null @@ -1,19 +0,0 @@ -@import 'mixins'; -@import 'functions'; - -.influence-info { - em { - font-weight: bolder; - } - - i { - font-style: italic; - } - - &__section { - padding: 0.5em 0; - @include break(medium) { - padding: 0 .5em; - } - } -} \ No newline at end of file diff --git a/src/components/Vote/Vote.jsx b/src/components/Vote/Vote.jsx index c913a5c50363..afd37f9ac1a5 100755 --- a/src/components/Vote/Vote.jsx +++ b/src/components/Vote/Vote.jsx @@ -1,30 +1,19 @@ import React from 'react'; import Interactive from 'antwar-interactive'; import Container from '../Container/Container'; -import VoteApp from './App'; -import '../../styles'; +import VoteApp from 'webpack.vote'; +import 'webpack.vote/dist/style.min.css'; import './Vote.scss'; -import './App.scss'; -import './Influence.scss'; -import './Button/Button.scss'; -const Vote = ({ section, page }) => { - let arr = page.url.split('/').filter(Boolean); - let name = arr[arr.length - 1]; - - return ( -Golden Influence
-Golden Influence is equal to 100 normal influence. Golden Influence is obtained by being a backer or sponsor on our Open Collective page.
-- - - ); -}; +const Vote = ({ section, page }) => ( +- -- + +); Vote.title = 'Vote'; diff --git a/src/components/Vote/Vote.scss b/src/components/Vote/Vote.scss index 8aa896a548e1..d9efe95ce407 100755 --- a/src/components/Vote/Vote.scss +++ b/src/components/Vote/Vote.scss @@ -2,3 +2,10 @@ @import 'mixins'; @import 'functions'; +.vote { + h1, h2, h3, h4, h5, h6 { + font-family: $font-stack-heading; + font-weight: 600; + color: getColor(fiord); + } +} diff --git a/src/components/Vote/api.dev.js b/src/components/Vote/api.dev.js deleted file mode 100755 index 8aac367b8abc..000000000000 --- a/src/components/Vote/api.dev.js +++ /dev/null @@ -1,161 +0,0 @@ -let usedCurrencies = { - influence: 100, - goldenInfluence: 100 -}; -let totalCurrencies = { - influence: 1000, - goldenInfluence: 300 -}; -let lists = { - todo: { - possibleVotes: [ - { - name: "influence", - currency: "influence", - score: 1, - color: "blue" - }, - { - name: "golden", - currency: "goldenInfluence", - score: 1, - color: "#bfa203" - } - ], - items: [ - { id: "1234", list: "todo", title: "Finish up MVP documentation", description: "Take care for the remaining issues in the webpack.js.org repo which are relevant for the MVP.", influence: 15 }, - { id: "2345", list: "todo", title: "Review whole documentation", description: "Read over **all** of the documentation to find errors.", golden: 20 }, - ] - } -}; -let allItems = { - "1234": lists.todo.items[0], - "2345": lists.todo.items[1], -}; - -function delay(time) { - return new Promise(function (fulfill) { - setTimeout(fulfill, time); - }); -} - -function clone(json) { - return JSON.parse(JSON.stringify(json)); -} - -export function isLoginActive() { - return /^\?login=/.test(window.location.search); -} - -export function startLogin(callbackUrl) { - window.location.search = "?login=" + encodeURIComponent(callbackUrl); - return Promise.resolve(); -} - -export function continueLogin() { - if(/^\?login=/.test(window.location.search)) { - return delay(2000).then(() => { - setTimeout(() => window.location = decodeURIComponent(window.location.search.substr(7), 100)); - return "developer"; - }); - } - return Promise.resolve(); -} - -export function getSelf(token) { - if(token !== "developer") - return Promise.reject(new Error("Not logged in as developer")); - return delay(500).then(() => ({ - login: "dev", - name: "Developer", - avatar: "https://github.com/webpack.png", - currencies: [ - { name: "influence", displayName: "Influence", description: "Some **description**", value: totalCurrencies.influence, used: usedCurrencies.influence, remaining: totalCurrencies.influence - usedCurrencies.influence }, - { name: "goldenInfluence", displayName: "Golden Influence", description: "Some **description**", value: totalCurrencies.goldenInfluence, used: usedCurrencies.goldenInfluence, remaining: totalCurrencies.goldenInfluence - usedCurrencies.goldenInfluence } - ] - })); -} - -export function getList(token, name) { - const loggedIn = token === "developer"; - const listData = lists[name]; - return delay(500).then(() => ({ - name: name, - displayName: "DEV: " + name, - description: "Some **description**", - lockable: true, - deletable: true, - archivable: true, - isAdmin: true, - possibleVotes: listData.possibleVotes, - items: lists[name].items.map(item => { - const votes = listData.possibleVotes.map(pv => ({ - name: pv.name, - votes: (item[pv.name] || 0) + Math.floor(Math.random() * 100) - })); - const score = listData.possibleVotes.map((pv, i) => { - return pv.score * votes[i].votes; - }).reduce((a, b) => a + b, 0); - return { - id: item.id, - list: item.list, - title: item.title, - description: item.description, - votes, - userVotes: loggedIn ? listData.possibleVotes.map(pv => ({ - name: pv.name, - votes: item[pv.name] || 0 - })) : undefined, - score - }; - }).sort((a, b) => b.score - a.score) - })); -} - -export function createItem(token, list, title, description) { - if(token !== "developer") - return Promise.reject(new Error("Not logged in as developer")); - let newItem = { - id: Math.random() + "", - list, - title, - description - }; - allItems[newItem.id] = newItem; - lists[list].items.push(newItem); - return delay(500).then(() => ({ - ...newItem, - votes: lists[list].possibleVotes.map(pv => ({ - name: pv.name, - votes: 0 - })), - userVotes: lists[list].possibleVotes.map(pv => ({ - name: pv.name, - votes: 0 - })), - score: 0 - })); -} - -export function vote(token, itemId, voteName, value) { - if(token !== "developer") - return Promise.reject(new Error("Not logged in as developer")); - var listId = allItems[itemId].list; - let listData = lists[listId]; - let pv = listData.possibleVotes.filter(pv => pv.name === voteName)[0]; - if(pv.currency) { - usedCurrencies[pv.currency] += value; - } - allItems[itemId][voteName] = (allItems[itemId][voteName] || 0) + value; - return delay(500).then(() => true); -} - -export function configItem(token, itemId, config) { - if(token !== "developer") - return Promise.reject(new Error("Not logged in as developer")); - var item = allItems[itemId]; - Object.keys(config).forEach(key => { - item[key] = config[key]; - }); - return delay(500).then(() => true); -} diff --git a/src/components/Vote/api.js b/src/components/Vote/api.js deleted file mode 100755 index e29c7077fb58..000000000000 --- a/src/components/Vote/api.js +++ /dev/null @@ -1,139 +0,0 @@ -import { - isLoginActive as devIsLoginActive, - startLogin as devStartLogin, - continueLogin as devContinueLogin, - getSelf as devGetSelf, - getList as devGetList, - createItem as devCreateItem, - vote as devVote, - configItem as devConfigItem -} from "./api.dev"; - -const API_URL = "https://oswils44oj.execute-api.us-east-1.amazonaws.com/production/"; -const GITHUB_CLIENT_ID = "4d355e2799cb8926c665"; -const PRODUCTION_HOST = "webpack.js.org"; - -// You can test the production mode with a host entry, -// or by setting PRODUCTION_HOST to "localhost:3000" and stealing localStorage.voteAppToken from the production side. - -function checkResult(result) { - if(!result) - throw new Error("No result received"); - if(result.errorMessage) - throw new Error(result.errorMessage); - return result; -} - -export function isLoginActive() { - if(window.location.host !== PRODUCTION_HOST) - return devIsLoginActive(); - return /^\?code=([^&]*)&state=([^&]*)/.test(window.location.search); -} - -export function startLogin(callbackUrl) { - if(window.location.host !== PRODUCTION_HOST) - return devStartLogin(callbackUrl); - let state = "" + Math.random(); - window.localStorage.githubState = state; - window.location = "https://github.com/login/oauth/authorize?client_id=" + GITHUB_CLIENT_ID + "&scope=user:email&state=" + state + "&allow_signup=false&redirect_uri=" + encodeURIComponent(callbackUrl); - return Promise.resolve(); -} - -export function continueLogin() { - if(window.location.host !== PRODUCTION_HOST) - return devContinueLogin(); - const match = /^\?code=([^&]*)&state=([^&]*)/.exec(window.location.search); - if(match) { - return login(match[1], match[2]).then(result => { - setTimeout(() => { - let href = window.location.href; - window.location = href.substr(0, href.length - window.location.search.length); - }, 100); - return result; - }); - } - return Promise.resolve(); -} - -function login(code, state) { - if(state !== window.localStorage.githubState) - return Promise.reject(new Error("Request state doesn't match (Login was triggered by 3rd party)")); - delete window.localStorage.githubState; - return fetch(API_URL + "/login", { - headers: { - "Content-Type": "application/json" - }, - method: "POST", - body: JSON.stringify({ - code, - state - }) - }).then((res) => res.json()).then(checkResult).then(result => { - if(!result.token) - throw new Error("No token received from API"); - return result.token; - }); -} - -export function getSelf(token) { - if(window.location.host !== PRODUCTION_HOST) - return devGetSelf(token); - return fetch(API_URL + "/self?token=" + token, { - mode: "cors" - }).then((res) => res.json()).then(checkResult); -} - -export function getList(token, name) { - if(window.location.host !== PRODUCTION_HOST) - return devGetList(token, name); - return fetch(API_URL + "/list/" + name + (token ? "?token=" + token : ""), { - mode: "cors" - }).then((res) => res.json()).then(checkResult); -} - -export function createItem(token, list, title, description) { - if(window.location.host !== PRODUCTION_HOST) - return devCreateItem(token, list, title, description); - return fetch(API_URL + "/list/" + list + "?token=" + token, { - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - title, - description - }), - method: "POST" - }).then((res) => res.json()).then(checkResult); -} - -export function vote(token, itemId, voteName, value) { - if(window.location.host !== PRODUCTION_HOST) - return devVote(token, itemId, voteName, value); - return fetch(API_URL + "/vote/" + itemId + "/" + voteName + "?token=" + token, { - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - count: value - }), - method: "POST" - }).then((res) => res.json()).then(checkResult).then(result => { - return true; - }); -} - -export function configItem(token, itemId, config) { - if(window.location.host !== PRODUCTION_HOST) - return devConfigItem(token, itemId, config); - return fetch(API_URL + "/config/" + itemId + "?token=" + token, { - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - config: config - }), - method: "POST" - }).then((res) => res.json()).then(checkResult).then(result => { - return true; - }); -} diff --git a/src/content/api/cli.md b/src/content/api/cli.md index 85f4c104f6ff..0c0bda477e18 100755 --- a/src/content/api/cli.md +++ b/src/content/api/cli.md @@ -4,6 +4,7 @@ sort: 2 contributors: - ev1stensberg - simon04 + - tbroadley related: - title: Analyzing Build Statistics url: https://survivejs.com/webpack/optimizing-build/analyzing-build-statistics/ @@ -215,7 +216,6 @@ webpack.js index=./src/index.js index2=./src/index2.js --output-path='./dist' -- 参数 | 说明 ------------------------- | ---------------------- `--watch`, `-w` | 观察文件系统的变化 -`--save`, `-s` | 在保存的时候重新编译,无论文件是否变化 `--watch-aggregate-timeout` | 指定一个毫秒数,在这个时间内,文件若发送了多次变化,会被合并 `--watch-poll` | 轮询观察文件变化的时间间隔(同时会打开轮询机制) `--watch-stdin`, `--stdin` | 当 stdin 关闭时,退出进程 diff --git a/src/content/api/hot-module-replacement.md b/src/content/api/hot-module-replacement.md index c9cc3f85d754..d214d6172483 100755 --- a/src/content/api/hot-module-replacement.md +++ b/src/content/api/hot-module-replacement.md @@ -3,6 +3,7 @@ title: 模块热替换(Hot Module Replacement) contributors: - sokra - skipjack + - tbroadley related: - title: 概念 - 模块热替换(Hot Module Replacement) url: /concepts/hot-module-replacement @@ -117,7 +118,7 @@ module.hot.apply(options).then(outdatedModules => { - `ignoreUnaccepted` (boolean): Ignore changes made to unaccepted modules. - `ignoreDeclined` (boolean): Ignore changes made to declined modules. -- `ignoreErrored` (boolean): Ignore errors throw in accept handlers, error handlers and while reevaulating module. +- `ignoreErrored` (boolean): Ignore errors throw in accept handlers, error handlers and while reevaluating module. - `onDeclined` (function(info)): Notifier for declined modules - `onUnaccepted` (function(info)): Notifier for unaccepted modules - `onAccepted` (function(info)): Notifier for accepted modules diff --git a/src/content/api/index.md b/src/content/api/index.md index df95f7f100ff..d159cab85d6b 100755 --- a/src/content/api/index.md +++ b/src/content/api/index.md @@ -1,6 +1,8 @@ --- title: 引导 sort: 1 +contributors: + - tbroadley --- 可以使用各种接口来定制化编译过程(compilation process)。一些特性会在几个接口之间重叠,例如,配置选项可能会从 CLI 标记(flag)中获取参数,而其他已存在特性,则只能通过某个接口去获取。以下高级信息可以帮助你起步。 diff --git a/src/content/api/loaders.md b/src/content/api/loaders.md index 77a7f95b68a3..7f042856e786 100755 --- a/src/content/api/loaders.md +++ b/src/content/api/loaders.md @@ -4,22 +4,23 @@ sort: 4 contributors: - TheLarkInn - jhnns + - tbroadley --- -所谓 loader 只是导出为一个函数的 JavaScript 模块。[loader runner](https://github.com/webpack/loader-runner) 会调用这个函数,然后把上一个 loader 产生的结果或者资源文件(resource file)传入进去。函数的 `this` 上下文将由 webpack 填充,并且 [loader runner](https://github.com/webpack/loader-runner) 带有一些有用方法,可以使 loader 改变为异步调用方式,或者获取 query 参数。 +所谓 loader 只是一个导出为函数的 JavaScript 模块。[loader runner](https://github.com/webpack/loader-runner) 会调用这个函数,然后把上一个 loader 产生的结果或者资源文件(resource file)传入进去。函数的 `this` 上下文将由 webpack 填充,并且 [loader runner](https://github.com/webpack/loader-runner) 具有一些有用方法,可以使 loader 改变为异步调用方式,或者获取 query 参数。 第一个 loader 的传入参数只有一个:资源文件(resource file)的内容。compiler 需要得到最后一个 loader 产生的处理结果。这个处理结果应该是 `String` 或者 `Buffer`(被转换为一个 string),代表了模块的 JavaScript 源码。另外还可以传递一个可选的 SourceMap 结果(格式为 JSON 对象)。 -如果是单个处理结果,可以在**同步模式**中直接返回。如果有多个处理结果,则需要调用 `this.callback()`。在**异步模式**中,必须调用 `this.async()`,来指示 [loader runner](https://github.com/webpack/loader-runner) 等待异步结果,它会返回 `this.callback()` 回调函数,随后 loader 必须返回 `undefined` 并且调用该回调函数。 +如果是单个处理结果,可以在**同步模式**中直接返回。如果有多个处理结果,则必须调用 `this.callback()`。在**异步模式**中,必须调用 `this.async()`,来指示 [loader runner](https://github.com/webpack/loader-runner) 等待异步结果,它会返回 `this.callback()` 回调函数,随后 loader 必须返回 `undefined` 并且调用该回调函数。 ## 示例 -The following sections provide some basic examples of the different types of loaders. Note that the `map` and `meta` parameters are optional, see [`this.callback`](/api/loaders#this-callback) below. +以下部分提供了不同类型的 loader 的一些基本示例。注意,`map` 和 `meta` 参数是可选的,查看下面的 [`this.callback`](/api/loaders#this-callback)。 ### 同步 loader -Either `return` or `this.callback` can be used to return the transformed `content` synchronously: +无论是 `return` 还是 `this.callback` 都可以同步地返回转换后的 `content` 内容: __sync-loader.js__ @@ -29,20 +30,20 @@ module.exports = function(content, map, meta) { }; ``` -The `this.callback` method is more flexible as it allows multiple arguments to be passed as opposed to just the `content`. +`this.callback` 方法则更灵活,因为它允许传递多个参数,而不仅仅是`content`。 __sync-loader-with-multiple-results.js__ ``` js module.exports = function(content, map, meta) { this.callback(null, someSyncOperation(content), sourceMaps, meta); - return; // 当调用callback()时总是返回 undefined + return; // 当调用 callback() 时总是返回 undefined }; ``` ### 异步 loader -For asynchronous loaders, [`this.async`](/api/loaders#this-async) is used to retrieve the `callback` function: +对于异步 loader,使用 [`this.async`](/api/loaders#this-async) 来获取 `callback` 函数: __async-loader.js__ @@ -68,7 +69,7 @@ module.exports = function(content, map, meta) { }; ``` -T> loader 最初被设计为可以在同步 loader pipeline(如 Node.js ,使用 [enhanced-require](https://github.com/webpack/enhanced-require)),与异步 pipeline(如 webpack )中运行。然而在 Node.js 这样的单线程环境下进行耗时长的同步计算不是个好主意,我们建议尽可能地使您的 loader 异步化。但如果计算量很小,同步 loader 也是可以的。 +T> loader 最初被设计为可以在同步 loader pipeline(如 Node.js ,使用 [enhanced-require](https://github.com/webpack/enhanced-require)),与异步 pipeline(如 webpack )中运行。然而在 Node.js 这样的单线程环境下进行耗时长的同步计算不是个好主意,我们建议尽可能地使你的 loader 异步化。但如果计算量很小,同步 loader 也是可以的。 ### "Raw" loader @@ -88,11 +89,33 @@ module.exports.raw = true; ``` -### Pitching loader +### 越过 loader(Pitching loader) -loader **总是**从右到左地被调用,但是在一些情况下,loader 不需要关心之前处理的结果或者资源(resource),而是只关心**元数据(metadata)**。在 loader 被调用前(从右到左),loader 中的 `pitch` 方法会**从左到右**依次被调用。 +loader __总是__从右到左地被调用。有些情况下,loader 只关心 request 后面的__元数据(metadata)__,并且忽略前一个 loader 的结果。在实际(从右到左)执行 loader 之前,会先__从左到右__调用 loader 上的 `pitch` 方法。对于以下 [`use`](/configuration/module#rule-use) 配置: -如果中间某个 loader 的 `pitch` 方法返回了一个值,那么剩下的 loader 都会被跳过,转而从当前 loader 开始向左调用 loader。`data`可以在 pitch 和普通的 loader 调用间传递。 +``` js +use: [ + 'a-loader', + 'b-loader', + 'c-loader' +] +``` + +将会发生这些步骤: + +``` diff +|- a-loader `pitch` + |- b-loader `pitch` + |- c-loader `pitch` + |- requested module is picked up as a dependency + |- c-loader normal execution + |- b-loader normal execution +|- a-loader normal execution +``` + +那么,为什么 loader 可以利用 "跳跃(pitching)" 阶段呢? + +首先,传递给 `pitch` 方法的 `data`,在执行阶段也会暴露在 `this.data` 之下,并且可以用于在循环时,捕获和共享前面的信息。 ``` js module.exports = function(content) { @@ -100,20 +123,41 @@ module.exports = function(content) { }; module.exports.pitch = function(remainingRequest, precedingRequest, data) { - if(someCondition()) { - // 直接返回 - return "module.exports = require(" + JSON.stringify("-!" + remainingRequest) + ");"; - } data.value = 42; }; ``` +其次,如果某个 loader 在 `pitch` 方法中给出一个结果,那么这个过程会回过身来,并跳过剩下的 loader。在我们上面的例子中,如果 `b-loader` 的 `pitch` 方法返回了一些东西: + +``` js +module.exports = function(content) { + return someSyncOperation(content); +}; + +module.exports.pitch = function(remainingRequest, precedingRequest, data) { + if (someCondition()) { + return "module.exports = require(" + JSON.stringify("-!" + remainingRequest) + ");"; + } +}; +``` + +上面的步骤将被缩短为: + +``` diff +|- a-loader `pitch` + |- b-loader `pitch` returns a module +|- a-loader normal execution +``` + +查看 [bundle-loader](https://github.com/webpack-contrib/bundle-loader),了解如何以更有意义的方式使用此过程。 + ## loader 上下文 -loader context 表示在 loader 内使用 `this` 可以访问的一些方法或属性 +loader context 表示在 loader 内使用 `this` 可以访问的一些方法或属性。 -假设我们在 `/abc/file.js` 中这样请求加载别的模块: +假设我们这样请求加载别的模块: +在 `/abc/file.js` 中: ``` js require("./loader1?xyz!loader2!./resource?rrr"); @@ -127,14 +171,14 @@ require("./loader1?xyz!loader2!./resource?rrr"); ### `this.context` -**模块所在的目录。**某些场景下这可能会有用处。 +**模块所在的目录。**可以用作解析其他模块路径的上下文。 在我们的例子中:这个属性为 `/abc`,因为 `resource.js` 在这个目录中 ### `this.request` -被解析出来的请求字符串。 +被解析出来的 request 字符串。 在我们的例子中:`"/abc/loader1.js?xyz!/abc/node_modules/loader2/index.js!/abc/resource.js?rrr"` @@ -163,21 +207,21 @@ this.callback( 1. 第一个参数必须是 `Error` 或者 `null` 2. 第二个参数是一个 `string` 或者 [`Buffer`](https://nodejs.org/api/buffer.html)。 3. 可选的:第三个参数必须是一个可以被[这个模块](https://github.com/mozilla/source-map)解析的 source map。 -4. 可选的:The fourth option, ignored by webpack, can be anything (e.g. some meta data). +4. 可选的:第四个选项,会被 webpack 忽略,可以是任何东西(例如一些元数据)。 -T> It can be useful to pass an abstract syntax tree (AST), like [`ESTree`](https://github.com/estree/estree), as the fourth argument (`meta`) to speed up the build time if you want to share common ASTs between loaders. +T> 可以将抽象语法树(abstract syntax tree - AST)(例如 [`ESTree`](https://github.com/estree/estree))作为第四个参数(`meta`),如果你想在多个 loader 之间共享通用的 AST,这样做有助于加速编译时间。 如果这个函数被调用的话,你应该返回 undefined 从而避免含糊的 loader 结果。 ### `this.async` -告诉 [loader-runner](https://github.com/webpack/loader-runner) 这个loader将会异步地回调。返回`this.callback`。 +告诉 [loader-runner](https://github.com/webpack/loader-runner) 这个 loader 将会异步地回调。返回 `this.callback`。 ### `this.data` -在 pitch 阶段和正常阶段之间共享的数据对象。 +在 pitch 阶段和正常阶段之间共享的 data 对象。 ### `this.cacheable` @@ -225,12 +269,12 @@ loaders = [{request: string, path: string, query: string, module: function}] 当前 loader 在 loader 数组中的索引。 -在我们的示例中:loader1:`0`,loader2:`1` +在我们的示例中:loader1 中得到:`0`,loader2 中得到:`1` ### `this.resource` -请求的资源部分,包括 query 参数。 +request 中的资源部分,包括 query 参数。 在我们的示例中:`"/abc/resource.js?rrr"` @@ -258,14 +302,14 @@ loaders = [{request: string, path: string, query: string, module: function}] ### `this.webpack` -如果是 Webpack 编译的,这个布尔值会被设置为真。 +如果是由 webpack 编译的,这个布尔值会被设置为真。 -T> loader 最初被设计为可以同时当 Babel transform 用。如果你编写了一个 loader 可以同时兼容二者,那么可以使用这个属性了解是否存在可用的 loaderContext 和 Webpack 的特性。 +T> loader 最初被设计为可以同时当 Babel transform 用。如果你编写了一个 loader 可以同时兼容二者,那么可以使用这个属性了解是否存在可用的 loaderContext 和 webpack 特性。 ### `this.sourceMap` -应该生成一个source map。因为生成 source map 可能会非常耗时,你应该确认 source map 确实被请求了。 +应该生成一个 source map。因为生成 source map 可能会非常耗时,你应该确认 source map 确实有必要请求。 ### `this.emitWarning` @@ -292,7 +336,7 @@ emitError(error: Error) loadModule(request: string, callback: function(err, source, sourceMap, module)) ``` -解析给定的 request 到一个模块,应用所有配置的 loader ,并且利用生成的 source 、sourceMap 和 模块实例(通常是 [`NormalModule`](https://github.com/webpack/webpack/blob/master/lib/NormalModule.js) 的一个实例),来进行回调。如果你需要知道其他模块的源代码来生成结果的话,你可以使用这个函数。 +解析给定的 request 到一个模块,应用所有配置的 loader ,并且在回调函数中传入生成的 source 、sourceMap 和 模块实例(通常是 [`NormalModule`](https://github.com/webpack/webpack/blob/master/lib/NormalModule.js) 的一个实例)。如果你需要获取其他模块的源代码来生成结果的话,你可以使用这个函数。 ### `this.resolve` @@ -311,7 +355,7 @@ addDependency(file: string) dependency(file: string) // 简写 ``` -加入一个文件作为产生 loader 结果的依赖,使它们的任何变化可以被监听到。例如,[html-loader](https://github.com/webpack/html-loader) 就使用了这个技巧。当它发现 `src` 和 `src-set` 属性时,就会把这些属性上的 url 加入到被解析的 html 文件的依赖中。 +加入一个文件作为产生 loader 结果的依赖,使它们的任何变化可以被监听到。例如,[`html-loader`](https://github.com/webpack/html-loader) 就使用了这个技巧,当它发现 `src` 和 `src-set` 属性时,就会把这些属性上的 url 加入到被解析的 html 文件的依赖中。 ### `this.addContextDependency` @@ -320,7 +364,7 @@ dependency(file: string) // 简写 addContextDependency(directory: string) ``` -把文件夹作为 loader 的依赖加入。 +把文件夹作为 loader 结果的依赖加入。 ### `this.clearDependencies` @@ -329,7 +373,7 @@ addContextDependency(directory: string) clearDependencies() ``` -移除 loader 所有的依赖。甚至自己和其它 loader 的初始依赖。考虑使用 `pitch`。 +移除 loader 结果的所有依赖。甚至自己和其它 loader 的初始依赖。考虑使用 `pitch`。 ### `this.emitFile` @@ -338,7 +382,7 @@ clearDependencies() emitFile(name: string, content: Buffer|string, sourceMap: {...}) ``` -产生一个文件。这是 webpack 独有的(原文:This is webpack-specific)。 +产生一个文件。这是 webpack 特有的。 ### `this.fs` @@ -346,7 +390,7 @@ emitFile(name: string, content: Buffer|string, sourceMap: {...}) 用于访问 `compilation` 的 `inputFileSystem` 属性。 -## Deprecated context properties +## 废弃的上下文属性 W> 强烈建议不要使用这些属性,因为我们打算移除它们。它们仍然列在此处用于文档目的。 @@ -357,7 +401,7 @@ W> 强烈建议不要使用这些属性,因为我们打算移除它们。它 exec(code: string, filename: string) ``` -以模块的方式执行一些代码片段。See [this comment](https://github.com/webpack/webpack.js.org/issues/1268#issuecomment-313513988) for a replacement method if needed. +以模块的方式执行一些代码片段。如果需要,请查看[这里的评论](https://github.com/webpack/webpack.js.org/issues/1268#issuecomment-313513988)以获取替换方法。 ### `this.resolveSync` @@ -366,7 +410,7 @@ exec(code: string, filename: string) resolveSync(context: string, request: string) -> string ``` -像 require 表达式一样解析一个 request 。(同步) +像 require 表达式一样解析一个 request。 ### `this.value` @@ -376,7 +420,7 @@ resolveSync(context: string, request: string) -> string ### `this.inputValue` -从上一个 loader 那里传递过来的值。如果你会以模块的方式处理输入参数,建议预先读入这个变量。(为了性能因素) +从上一个 loader 那里传递过来的值。如果你会以模块的方式处理输入参数,建议预先读入这个变量(为了性能因素)。 ### `this.options` @@ -386,7 +430,7 @@ options 的值将会传递给 Complier ### `this.debug` -一个布尔值,当处于 debug 模式时为真。 +一个布尔值,当处于 debug 模式时为 true。 ### `this.minimize` @@ -396,12 +440,12 @@ options 的值将会传递给 Complier ### `this._compilation` -一种 hack 写法。用于访问 Webpack 的 Compilation 对象。 +一种 hack 写法。用于访问 webpack 的 Compilation 对象。 ### `this._compiler` -一种 hack 写法。用于访问 Webpack 的 Compiler 对象。 +一种 hack 写法。用于访问 webpack 的 Compiler 对象。 ### `this._module` diff --git a/src/content/api/module-variables.md b/src/content/api/module-variables.md index 4c59b5918cc0..2133e043acc1 100755 --- a/src/content/api/module-variables.md +++ b/src/content/api/module-variables.md @@ -6,6 +6,7 @@ contributors: - skipjack - sokra - ahmehri + - tbroadley related: - title: CommonJS url: https://en.wikipedia.org/wiki/CommonJS diff --git a/src/content/concepts/index.md b/src/content/concepts/index.md index 7f8c9973c909..deaa8cb1a0c3 100755 --- a/src/content/concepts/index.md +++ b/src/content/concepts/index.md @@ -74,12 +74,14 @@ T> `output` 属性还有[更多可配置的特性](/configuration/output),如 本质上,webpack loader 将所有类型的文件,转换为应用程序的依赖图可以直接引用的模块。 +W> 注意,loader 能够 `import` 导入任何类型的模块(例如 `.css` 文件),这是 webpack 特有的功能,其他打包程序或任务执行器的可能并不支持。我们认为这种语言扩展是有很必要的,因为这可以使开发人员创建出更准确的依赖关系图。 + 在更高层面,在 webpack 的配置中 **loader** 有两个目标。 1. 识别出应该被对应的 loader 进行转换的那些文件。(使用 `test` 属性) 2. 转换这些文件,从而使其能够被添加到依赖图中(并且最终添加到 bundle 中)(`use` 属性) -**webpack.config.js** +__webpack.config.js__ ```javascript const path = require('path'); diff --git a/src/content/concepts/loaders.md b/src/content/concepts/loaders.md index 0e222a46dd4c..c9a245e7d31e 100755 --- a/src/content/concepts/loaders.md +++ b/src/content/concepts/loaders.md @@ -101,7 +101,7 @@ webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader' ## Loader 特性 -* loader 支持链式传递。能够对资源使用流水线(pipeline)。一组链式的 loader 将按照先后顺序进行编译。loader 链中的第一个 loader 返回值给下一个 loader。在最后一个 loader,返回 webpack 所预期的 JavaScript。 +* loader 支持链式传递。能够对资源使用流水线(pipeline)。一组链式的 loader 将按照相反的顺序执行。loader 链中的第一个 loader 返回值给下一个 loader。在最后一个 loader,返回 webpack 所预期的 JavaScript。 * loader 可以是同步的,也可以是异步的。 * loader 运行在 Node.js 中,并且能够执行任何可能的操作。 * loader 接收查询参数。用于对 loader 传递配置。 @@ -110,7 +110,8 @@ webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader' * 插件(plugin)可以为 loader 带来更多特性。 * loader 能够产生额外的任意文件。 -loader 通过(loader)预处理函数,为 JavaScript 生态系统提供了更多能力。用户现在可以更加灵活地引入细粒度逻辑,例如压缩、打包、语言翻译和[其他更多](/loaders)。 +loader 通过(loader)预处理函数,为 JavaScript 生态系统提供了更多能力。 +用户现在可以更加灵活地引入细粒度逻辑,例如压缩、打包、语言翻译和[其他更多](/loaders)。 ## 解析 Loader diff --git a/src/content/configuration/configuration-languages.md b/src/content/configuration/configuration-languages.md index 1775c9ea3dd3..009f18edde36 100755 --- a/src/content/configuration/configuration-languages.md +++ b/src/content/configuration/configuration-languages.md @@ -7,6 +7,7 @@ contributors: - tarang9211 - simon04 - peterblazejewicz + - youta1119 --- webpack 接受以多种编程和数据语言编写的配置文件。支持的文件扩展名列表,可以在 [node-interpret](https://github.com/js-cli/js-interpret) 包中找到。使用 [node-interpret](https://github.com/js-cli/js-interpret),webpack 可以处理许多不同类型的配置文件。 @@ -39,6 +40,48 @@ const config: webpack.Configuration = { export default config; ``` +Not that you'll also need to check your `tsconfig.json` file. If the module in `compilerOptions` in `tsconfig.json` is `commonjs`, the setting is complete, else webpack will fail with an error. This occurs because `ts-node` does not support any module syntax other than `commonjs`. + +There are two solutions to this issue: + +- Modify `tsconfig.json`. +- Install `tsconfig-paths`. + +The __first option__ is to open your `tsconfig.json` file and look for `compilerOptions`. Set `target` to `"ES5"` and `module` to `"CommonJS"` (or completely remove the `module` option). + +The __second option__ is to install the `tsconfig-paths` package: + +``` bash +npm install --save-dev tsconfig-paths +``` + +And create a separate TypeScript configuration specifically for your webpack configs: + +__tsconfig-for-webpack-config.json__ + +``` json +{ + "compilerOptions": { + "module": "commonjs", + "target": "es5" + } +} +``` + +T> `ts-node` can resolve a `tsconfig.json` file using the environment variable provided by `tsconfig-path`. + +Then set the environment variable `process.env.TS_NODE_PROJECT` provided by `tsconfig-path` like so: + +__package.json__ + +```json +{ + "scripts": { + "build": "TS_NODE_PROJECT=\"tsconfig-for-webpack-config.json\" webpack" + } +} +``` + ## CoffeeScript diff --git a/src/content/configuration/devtool.md b/src/content/configuration/devtool.md index 59e37b1c74ba..f7d6bfb3982e 100755 --- a/src/content/configuration/devtool.md +++ b/src/content/configuration/devtool.md @@ -30,7 +30,7 @@ T> Instead of using the `devtool` option you can also use `SourceMapDevToolPlugi devtool | build | rebuild | production | quality ------------------------------ | ----- | ------- | ---------- | ----------------------------- -(none) | +++ | +++ | no | bundled code +(none) | +++ | +++ | yes | bundled code eval | +++ | +++ | no | generated code cheap-eval-source-map | + | ++ | no | transformed code (lines only) cheap-module-eval-source-map | o | ++ | no | original source (lines only) diff --git a/src/content/configuration/externals.md b/src/content/configuration/externals.md index 6c95b0f003cb..ddbc26b01483 100755 --- a/src/content/configuration/externals.md +++ b/src/content/configuration/externals.md @@ -9,7 +9,7 @@ contributors: `externals` 配置选项提供了「从输出的 bundle 中排除依赖」的方法。相反,所创建的 bundle 依赖于那些存在于用户环境(consumer's environment)中的依赖。此功能通常对 __library 开发人员__来说是最有用的,然而也会有各种各样的应用程序用到它。 -T> __用户(consumer)__,在这里是指,引用了「使用 webpack 打包的 library」 的任何终端用户的应用程序(end user application)。 +T> __用户(consumer)__,在这里是指,引用了「使用 webpack 打包的 library」的所有终端用户的应用程序(end user application)。 ## `externals` @@ -20,19 +20,19 @@ __防止__将某些 `import` 的包(package)__打包__到 bundle 中,而是在 例如,从 CDN 引入 [jQuery](https://jquery.com/),而不是把它打包: -**index.html** +__index.html__ -```html -... - -... + crossorigin="anonymous"> + ``` -**webpack.config.js** +__webpack.config.js__ -```javascript +``` js externals: { jquery: 'jQuery' } @@ -40,7 +40,7 @@ externals: { 这样就剥离了那些不需要改动的依赖模块,换句话,下面展示的代码还可以正常运行: -```javascript +``` js import $ from 'jquery'; $('.my-element').animate(...); @@ -48,22 +48,22 @@ $('.my-element').animate(...); 具有外部依赖(external dependency)的 bundle 可以在各种模块上下文(module context)中使用,例如 [CommonJS, AMD, 全局变量和 ES2015 模块](/concepts/modules)。外部 library 可能是以下任何一种形式: -* __root__ - 外部 library 能够作为全局变量使用。用户可以通过在 script 标签中引入来实现。这是 externals 的默认设置。 -* __commonjs__ - 用户(consumer)应用程序可能使用 CommonJS 模块系统,因此外部 library 应该使用 CommonJS 模块系统,并且应该是一个 CommonJS 模块。 -* __commonjs2__ - 类似上面几行,但导出的是 `module.exports.default`。 -* __amd__ - 类似上面几行,但使用 AMD 模块系统。 +- __root__:可以通过一个全局变量访问 library(例如,通过 script 标签)。 +- __commonjs__:可以将 library 作为一个 CommonJS 模块访问。 +- __commonjs2__:和上面的类似,但导出的是 `module.exports.default`. +- __amd__:类似于 `commonjs`,但使用 AMD 模块系统。 -`externals` 接受各种语法,并且按照不同方式去解释他们。 +可以接受各种语法…… ### string -externals 中的 `jQuery`,表示你的 bundle 需要访问全局形式的 `jQuery` 变量。 +请查看上面的例子。属性名称是 `jquery`,表示应该排除 `import $ from 'jquery'` 中的 `jquery` 模块。为了替换这个模块,`jQuery` 的值将被用来检索一个全局的 `jQuery` 变量。换句话说,当设置为一个字符串时,它将被视为`全局的`(定义在上面和下面)。 ### array -```javascript +``` js externals: { subtract: ['./math', 'subtract'] } @@ -74,7 +74,7 @@ externals: { ### object -```javascript +``` js externals : { react: 'react' } @@ -85,11 +85,11 @@ externals : { lodash : { commonjs: "lodash", amd: "lodash", - root: "_" // indicates global variable + root: "_" // 指向全局变量 } } -// or +// 或者 externals : { subtract : { @@ -98,16 +98,16 @@ externals : { } ``` -此语法用于描述所有外部 library 可用的访问方式。这里 `lodash` 这个外部 library 可以在 AMD 和 CommonJS 模块系统中通过 `lodash` 访问,但在全局变量形式下用 `_` 访问。`subtract` 可以通过全局 `math` 对象下的属性 `subtract` 访问(例如 `window['math']['subtract']`)。 +此语法用于描述外部 library 所有可用的访问方式。这里 `lodash` 这个外部 library 可以在 AMD 和 CommonJS 模块系统中通过 `lodash` 访问,但在全局变量形式下用 `_` 访问。`subtract` 可以通过全局 `math` 对象下的属性 `subtract` 访问(例如 `window['math']['subtract']`)。 ### function -It might be useful to define your own function to control the behavior of what you want to externalize from webpack. [webpack-node-externals](https://www.npmjs.com/package/webpack-node-externals), for example, excludes all modules from the node_modules and provides some options to, for example, whitelist packages. +It might be useful to define your own function to control the behavior of what you want to externalize from webpack. [webpack-node-externals](https://www.npmjs.com/package/webpack-node-externals), for example, excludes all modules from the `node_modules` directory and provides some options to, for example, whitelist packages. It basically comes down to this: -```javascript +``` js externals: [ function(context, request, callback) { if (/^yourregex$/.test(request)){ @@ -125,7 +125,7 @@ The `'commonjs ' + request` defines the type of module that needs to be external Every dependency that matches the given regular expression will be excluded from the output bundles. -```javascript +``` js externals: /^(jquery|\$)$/i ``` diff --git a/src/content/configuration/output.md b/src/content/configuration/output.md index 9fe25706cfa0..d5757b912deb 100755 --- a/src/content/configuration/output.md +++ b/src/content/configuration/output.md @@ -295,7 +295,7 @@ JSONP 函数用于异步加载(async load) chunk,或者拼接多个初始 chun `output.library` 的值的作用,取决于[`output.libraryTarget`](#output-librarytarget) 选项的值;完整的详细信息请查阅该章节。注意,`output.libraryTarget` 的默认选项是 `var`,所以如果使用以下配置选项: -```javascript +``` js output: { library: "MyLibrary" } @@ -303,6 +303,8 @@ output: { 如果生成的输出文件,是在 HTML 页面中作为一个 script 标签引入,则变量 `MyLibrary` 将与入口文件的返回值绑定。 +W> 注意,如果将`数组`作为 `entry`,那么只会暴露数组中的最后一个模块。如果将`对象`作为 `entry`,还可以使用`数组`语法暴露(具体查看[这个示例](https://github.com/webpack/webpack/tree/master/examples/multi-part-library) for details))。 + T> 有关 `output.library` 以及 `output.libraryTarget` 详细信息,请查看[创建 library 指南](/guides/author-libraries)。 @@ -312,41 +314,38 @@ T> 有关 `output.library` 以及 `output.libraryTarget` 详细信息,请查 > Default: `_entry_return_` -Configure which module or modules will be exposed via the `libraryTarget`. - -The default value `_entry_return_` is the namespace or default module returned by your entry file. - -The examples below demonstrate the effect of this config when using `libraryTarget: "var"`, but any target may be used. +Configure which module or modules will be exposed via the `libraryTarget`. The default `_entry_return_` value is the namespace or default module returned by your entry file. The examples below demonstrate the effect of this config when using `libraryTarget: "var"`, but any target may be used. The following configurations are supported: `libraryExport: "default"` - The **default export of your entry point** will be assigned to the library target: -```javascript +``` js // if your entry has a default export of `MyDefaultModule` var MyDefaultModule = _entry_return_.default; ``` `libraryExport: "MyModule"` - The **specified module** will be assigned to the library target: -```javascript +``` js var MyModule = _entry_return_.MyModule; ``` `libraryExport: ["MyModule", "MySubModule"]` - The array is interpreted as a **path to a module** to be assigned to the library target: -```javascript +``` js var MySubModule = _entry_return_.MyModule.MySubModule; ``` -如同以上示例中所展示,入口起点的返回值,与这些具名变量绑定在一起,因此,生成的 library 的用法如下: +With the `libraryExport` configurations specified above, the resulting libraries could be utilized as such: -```javascript +``` js MyDefaultModule.doSomething(); MyModule.doSomething(); MySubModule.doSomething(); ``` + ## `output.libraryTarget` `string` @@ -363,7 +362,7 @@ T> 注意,下面的示例代码中的 `_entry_return_` 是入口起点返回 `libraryTarget: "var"` - (默认值)当 library 加载完成,**入口起点的返回值**将分配给一个变量: -```javascript +``` js var MyLibrary = _entry_return_; // 在一个单独的 script…… @@ -375,7 +374,7 @@ W> 当使用此选项时,将 `output.library` 设置为空,会因为没有 `libraryTarget: "assign"` - 这将产生一个隐含的全局变量,可能会潜在地重新分配到全局中已存在的值(谨慎使用)。. -``` javascript +``` js MyLibrary = _entry_return_; ``` @@ -390,7 +389,7 @@ W> 当使用此选项时,将 `output.library` 设置为空,将产生一个 如果 `output.library` 未赋值为一个非空字符串,则默认行为是,将入口起点返回的所有属性都赋值给一个对象(此对象由 `output.libraryTarget` 特定),通过如下代码片段: -```javascript +``` js (function(e, a) { for(var i in a) e[i] = a[i]; }(${output.libraryTarget}, _entry_return_) ``` @@ -398,7 +397,7 @@ W> 注意,不设置 `output.library` 将导致由入口起点返回的所有 `libraryTarget: "this"` - **入口起点的返回值**将分配给 this 的一个属性(此名称由 `output.library` 定义)下,`this` 的含义取决于你: -```javascript +``` js this["MyLibrary"] = _entry_return_; // 在一个单独的 script…… @@ -408,7 +407,7 @@ MyLibrary.doSomething(); // 如果 this 是 window `libraryTarget: "window"` - **入口起点的返回值**将使用 `output.library` 中定义的值,分配给 `window` 对象的这个属性下。 -```javascript +``` js window["MyLibrary"] = _entry_return_; window.MyLibrary.doSomething(); @@ -417,7 +416,7 @@ window.MyLibrary.doSomething(); `libraryTarget: "global"` - **入口起点的返回值**将使用 `output.library` 中定义的值,分配给 `global` 对象的这个属性下。 -```javascript +``` js global["MyLibrary"] = _entry_return_; global.MyLibrary.doSomething(); @@ -426,7 +425,7 @@ global.MyLibrary.doSomething(); `libraryTarget: "commonjs"` - **入口起点的返回值**将使用 `output.library` 中定义的值,分配给 exports 对象。这个名称也意味着,模块用于 CommonJS 环境: -```javascript +``` js exports["MyLibrary"] = _entry_return_; require("MyLibrary").doSomething(); @@ -439,7 +438,7 @@ require("MyLibrary").doSomething(); `libraryTarget: "commonjs2"` - **入口起点的返回值**将分配给 `module.exports` 对象。这个名称也意味着模块用于 CommonJS 环境: -```javascript +``` js module.exports = _entry_return_; require("MyLibrary").doSomething(); @@ -456,7 +455,7 @@ AMD 模块要求入口 chunk(例如使用 `+